#Abundance graphs
#Load packages
library("tidyverse")
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
-- Attaching packages ---------------------------------------------------------------------------------------------------- tidyverse 1.3.0 --
v ggplot2 3.3.2 v purrr 0.3.4
v tibble 3.0.3 v dplyr 1.0.2
v tidyr 1.1.2 v stringr 1.4.0
v readr 1.3.1 v forcats 0.5.0
-- Conflicts ------------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
library("dada2")
Loading required package: Rcpp
library("biomformat")
library('vegan')
Loading required package: permute
Loading required package: lattice
This is vegan 2.5-6
library('readr')
library("dplyr") # To manipulate dataframes
library("readxl") # To read Excel files into R
library("ggplot2") # for high quality graphics
library("BiocManager")
Bioconductor version 3.11 (BiocManager 1.30.10), ?BiocManager::install for help
Bioconductor version '3.11' is out-of-date; the current release version '3.12' is available with R version '4.0'; see
https://bioconductor.org/install
library("phyloseq")
Registered S3 method overwritten by 'data.table':
method from
print.data.table
library("tidyr")
library("data.table")
data.table 1.13.0 using 2 threads (see ?getDTthreads). Latest news: r-datatable.com
Attaching package: 㤼㸱data.table㤼㸲
The following objects are masked from 㤼㸱package:dplyr㤼㸲:
between, first, last
The following object is masked from 㤼㸱package:purrr㤼㸲:
transpose
library("esquisse")
package 㤼㸱esquisse㤼㸲 was built under R version 4.0.3
#Colour palettes
#install.packages("esquisse")
library(wesanderson)
package 㤼㸱wesanderson㤼㸲 was built under R version 4.0.3
library(viridis)
Loading required package: viridisLite
library(RColorBrewer)
library(ggsci)
#Load in Data, merge tables
###read in biom-taxonomy for SILVA ####################################################
#SILVA
taxonomy45_SILVA <- read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V4V5/V4V5_SILVA_taxonomy.csv")
taxonomy68_SILVA <- read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V6V8/taxonomy_SILVA_V6V8.csv")
#RDP
taxonomy45_RDP <- read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V4V5/taxonomy_RDP_V4V5.csv")
taxonomy68_RDP <- read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V6V8/taxonomy_RDP_V6V8.csv")
#GreenGenes
taxonomy45_GG <- read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V4V5/taxonomy_greengenes_V4V5.csv")
taxonomy68_GG <- read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V6V8/taxonomy_greengenes_V6V8.csv")
taxonomy45_SILVA<-as.data.table(taxonomy45_SILVA)
taxonomy68_SILVA<-as.data.table(taxonomy68_SILVA)
taxonomy45_RDP<-as.data.table(taxonomy45_RDP)
taxonomy68_RDP<-as.data.table(taxonomy68_RDP)
taxonomy45_GG<-as.data.table(taxonomy45_GG)
taxonomy68_GG<-as.data.table(taxonomy68_GG)
###read in otu tables #################################################################
otu45<- read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V4V5/V4V5__ASV_table.csv", header = T) #,row.names=1
otu68<- read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V6V8/V6V8__ASV_table.csv", header = T)
head(otu45)
head(otu68)
#Convert to long format
otu_long45<-gather(otu45, Sample, Counts, "X3":"X157") #dashes got changed to dots for some reason
otu_long68<-gather(otu68, Sample, Counts, "o_122":"o_83") #dashes got changed to dots for some reason
#make a data.Table
otu_long45<-as.data.table(otu_long45)
otu_long68<-as.data.table(otu_long68)
otu_long45
otu_long68
###read in metadata file #################################################################
metaD45<-read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V4V5/metadata_16S_V4V5_jonesSound2019.txt", sep = "")
metaD45<-as.data.table(metaD45)
metaD45$Sample<-as.character(metaD45$Sample)
metaD45
metaD68<-read.csv("G:/Desktop/Folders/Edu/2] EAS/Thesis/Real_Content/Data_Files/V6V8/metadata_16S_V6V8_jonesSound2019.txt", sep = "")
metaD68<-as.data.table(metaD68)
metaD68$Sample<-as.character(metaD68$Sample)
metaD68
### Merge data tables #################################################################
# first set the keys to the common column:
setkey(otu_long68,Sample)
setkey(metaD68,Sample)
setkey(otu_long45,Sample)
setkey(metaD45,Sample)
# join the tables
OTU_Meta_Merge_45 <- merge(otu_long45,metaD45,by="Sample")
OTU_Meta_Merge_45
OTU_Meta_Merge_68 <- merge(otu_long68,metaD68,by="Sample")
OTU_Meta_Merge_68
#set key of OTU_Meta_Merge_45 as the OTUID to join the taxonomy table
setkey(OTU_Meta_Merge_45,OTUID)
setkey(taxonomy45,OTUID)
setkey(OTU_Meta_Merge_68,OTUID)
setkey(taxonomy68,OTUID)
#merge SILVA
SILVA_45_Merged <- merge(OTU_Meta_Merge_45,taxonomy45_SILVA)
setkey(SILVA_45_Merged, Sample)
SILVA_68_Merged <- merge(OTU_Meta_Merge_68,taxonomy68_SILVA)
setkey(SILVA_68_Merged, Sample)
#merge RDP
taxonomy45_RDP
RDP_45_Merged <- merge(OTU_Meta_Merge_45,taxonomy45_RDP)
setkey(RDP_45_Merged, Sample)
RDP_68_Merged <- merge(OTU_Meta_Merge_68,taxonomy68_RDP)
setkey(RDP_68_Merged, Sample)
#merge GG
GG_45_Merged <- merge(OTU_Meta_Merge_45,taxonomy45_GG)
setkey(GG_45_Merged, Sample)
GG_68_Merged <- merge(OTU_Meta_Merge_68,taxonomy68_GG)
setkey(GG_68_Merged, Sample)
#Format by metadata
#SILVA
SILVA45_Full <- metaD45[SILVA_45_Merged]
(SILVA45_Full)
SILVA68_Full <- metaD68[SILVA_68_Merged]
(SILVA68_Full)
#RDP
RDP45_Full <- metaD45[RDP_45_Merged]
(RDP45_Full)
RDP68_Full <- metaD68[RDP_68_Merged]
(RDP68_Full)
#GreenGenes
GG45_Full <- metaD45[GG_45_Merged]
(GG45_Full)
GG68_Full <- metaD68[GG_68_Merged]
(GG68_Full)
SILVA_OTU_Taxa45 <- merge(otu45,taxonomy45_SILVA)
SILVA_OTU_Taxa45
chloro_order_SILVA45 <- taxonomy45_SILVA %>% filter((Order == "Chloroplast") & (Order != ""))
chloro_order_SILVA45
chloro_order_SILVA68 <- taxonomy68_SILVA %>% filter((Order == "Chloroplast") & (Order != ""))
chloro_order_SILVA68
chloro_order_RDP45 <- taxonomy45_RDP %>% filter((Order == "Chloroplast") & (Order != ""))
chloro_order_RDP45
chloro_order_RDP68 <- taxonomy68_RDP %>% filter((Order == "Chloroplast") & (Order != ""))
chloro_order_RDP68
#Statistical differences in OTU table by primer region
#Kruskal Wallis test:
#http://www.sthda.com/english/wiki/kruskal-wallis-test-in-r
#https://stats.stackexchange.com/questions/443329/kruskal-wallis-test-for-multiple-variables-different-in-r-and-python
#kruskal.test(Primer ~ otu_full[,1], data = otu_full) ###Test one by one
otu_full <- merge(by = "OTUID", otu45, otu68, all.x = TRUE)
kruskal.test(otu_full[2:28], otu_full[29:55], data = otu_full) #Test range of columns against each other
topTaxaBoth_SILVA_namevec
[1] "Frankiales" "Microtrichales" "Bdellovibrionales" "Oceanospirillales" "Verrucomicrobiales"
[6] "Pirellulales" "Nitrosopumilales" "Sphingobacteriales" "Cellvibrionales" "Alteromonadales"
[11] "Sphingomonadales" "Rickettsiales" "Cytophagales" "SAR11 clade" "Rhodobacterales"
[16] "Chitinophagales" "Chloroplast" "" "Betaproteobacteriales" "Flavobacteriales"
#####Proportion plot for each sample with both primer, based on ORDER ######
#SILVA:
#Find top 20 orders and put them in a vector (used to filter)
top_SILVA45<- as.data.table(table(SILVA45_Full$Order)) #count by Order.
top_SILVA45<- top_SILVA45[order(top_SILVA45$N)]
top_SILVA45 <- slice_tail(top_SILVA45, n=20)
top_SILVA45 <- as.vector(tail(top_SILVA45$V1,20))
top_SILVA45 #Vector containing top 20
top_SILVA68<- as.data.table(table(SILVA68_Full$Order)) #count by Order.
top_SILVA68<- top_SILVA68[order(top_SILVA68$N)]
top_SILVA68 <- slice_tail(top_SILVA68, n=20)
top_SILVA68 <- as.vector(tail(top_SILVA68$V1,20))
top_SILVA68 #Vector containing top 20
top_GG45<- as.data.table(table(GG45_Full$Order)) #count by Order.
top_GG45<- top_GG45[order(top_GG45$N)]
top_GG45 <- slice_tail(top_GG45, n=20)
top_GG45 <- as.vector(tail(top_GG45$V1,20))
top_GG45 #Vector containing top 20
top_GG68<- as.data.table(table(GG68_Full$Order)) #count by Order.
top_GG68<- top_GG68[order(top_GG68$N)]
top_GG68 <- slice_tail(top_GG68, n=20)
top_GG68 <- as.vector(tail(top_GG68$V1,20))
top_GG68 #Vector containing top 20
top_RDP45<- as.data.table(table(RDP45_Full$Order)) #count by Order.
top_RDP45<- top_RDP45[order(top_RDP45$N)]
top_RDP45 <- slice_tail(top_RDP45, n=20)
top_RDP45 <- as.vector(tail(top_RDP45$V1,20))
top_RDP45 #Vector containing top 20
top_RDP68<- as.data.table(table(RDP68_Full$Order)) #count by Order.
top_RDP68<- top_RDP68[order(top_RDP68$N)]
top_RDP68 <- slice_tail(top_RDP68, n=20)
top_RDP68 <- as.vector(tail(top_RDP68$V1,20))
top_RDP68 #Vector containing top 20
#Filter results
top20_SILVA45 <- SILVA45_Full %>% filter(Order == top_SILVA45) #Filter for only the ones with the names of the top 20 orders
top20_SILVA68 <- SILVA68_Full %>% filter(Order == top_SILVA68) #Filter for only the ones with the names of the top 20 orders
top20_GG45 <- GG45_Full %>% filter(Order == top_GG45) #Filter for only the ones with the names of the top 20 orders
top20_GG68 <- GG68_Full %>% filter(Order == top_GG68) #Filter for only the ones with the names of the top 20 orders
top20_RDP45 <- RDP45_Full %>% filter(Order == top_RDP45) #Filter for only the ones with the names of the top 20 orders
top20_RDP68 <- RDP68_Full %>% filter(Order == top_RDP68) #Filter for only the ones with the names of the top 20 orders
GG45 <- ggplot(top20_GG45, aes(x = SAMPLE_NAME, y = Counts, fill = Order)) + geom_bar(position = "fill", stat = "identity")
ggplot(top20_GG45, aes(fill=Counts, y=1, x=1)) +
theme(axis.text.x= element_text(angle = 45, hjust = 1, size=7)) +guides(fill=guide_legend(title="Order"))+ylab(label="Relative abundance")+
ggtitle("Top 20 Orders from GreenGenes in samples sequenced by V4-V5 region")+ # for the main title
geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
GG45
GG68 <- ggplot(top20_GG68, aes(x = Counts, y = Sample, fill = Order)) + geom_bar(position = "fill", stat = "identity")
ggplot(top20_GG68, aes(fill=Counts, y=1, x=1)) +
ggtitle("Top 20 Orders from GreenGenes in samples sequenced by V6-V8 region")+ # for the main title
geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
GG68
S45 <- ggplot(top20_SILVA45, aes(x = Counts, y = Sample, fill = Order)) + geom_bar(position = "fill", stat = "identity")
ggplot(top20_SILVA45, aes(fill=Counts, y=1, x=1)) +
ggtitle("Top 20 Orders from SILVA in samples sequenced by V4-V5 region")+ # for the main title
geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
S45
S68 <- ggplot(top20_SILVA68, aes(x = Counts, y = Sample, fill = Order)) + geom_bar(position = "fill", stat = "identity")
ggplot(top20_SILVA68, aes(fill=Counts, y=1, x=1)) +
ggtitle("Top 20 Orders from SILVA in samples sequenced by V6-V8 region")+ # for the main title
geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
S68
RDP45 <- ggplot(top20_RDP45, aes(x = Counts, y = Sample, fill = Order)) + geom_bar(position = "fill", stat = "identity")
ggplot(top20_RDP45, aes(fill=Counts, y=1, x=1)) +
ggtitle("Top 20 Orders from GreenGenes in samples sequenced by V6-V8 region")+ # for the main title
geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
RDP45
#Working on assigning specific colours...
colourAssign = c("Frankiales"="blue","Microtrichales"="coral3","Marine Group II"="chartreuse4","Verrucomicrobiales"="deeppink3","Oceanospirillales"="darkviolet","Sphingobacteriales"="maroon3","Alteromonadales"="paleturquoise4","Rickettsiales"="seagreen4","Cellvibrionales"="orangered2","Pirellulales"="orange3","Nitrosopumilales"="royalblue3","Sphingomonadales"="raspbbrawn3","SAR11 clade"="navyblue","Cytophagales"="brown3","Rhodobacterales"="darkcyan","Chitinophagales"="firebrick3"," "="gray46","Chloroplast"="mediumseagreen","Betaproteobacteriales"="mediumpurple2","Flavobacteriales"="goldenrod1")
#colourAssign = c("blue","coral3","chartreuse4","deeppink3","darkviolet","maroon3","paleturquoise4","seagreen4","orangered2","orange3","royalblue3","raspbbrawn3","navyblue","brown3","darkcyan","firebrick3","gray46","mediumseagreen","mediumpurple2","goldenrod1")
RDP68 <- ggplot(top20_RDP68, aes(x = Counts, y = Sample, fill = Order)) + geom_bar(position = "fill", stat = "identity")
ggplot(top20_RDP68, aes(fill=Counts, y=1, x=1)) +
ggtitle("Top 20 Orders from GreenGenes in samples sequenced by V6-V8 region")+ # for the main title
geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9)+ # or some other arbitrarily large number
#scale_fill_manual("legend", values = colourAssign)
#theme_bw()+scale_fill_manual(values=colourAssign)
RDP68
? scale_fill_manual
#assign colour, each line is for specific phyla (more colour= for more phyla, where y (assignation)= my taxonomy):
col=c("blue", "chartreuse4", "darkgreen", "yellow", "goldenrod4", "chartreuse2", "darkolivegreen", "cornsilk", "cornsilk4")
col=c("blue", "chartreuse4", "darkgreen", "yellow","goldenrod", "darkgoldenrod2")
col=c("black", "purple")
long_trophs2 %>%
ggplot(aes(x=Depth, y=assignation, size = rel_abund, fill=Stage)) +
geom_point( colour="black", pch=21) + facet_grid(. ~ Stage, drop=TRUE,scale="free",space="free_x")+
theme_bw()+scale_fill_manual(values=col)+
theme(axis.text.x= element_text(angle = 45, hjust = 1, size=8))+
theme(axis.text.y= element_text(size=8))
#Top 20 phylum of each database and each primer as tables
#SILVA:
#Sort out the counts of Orders
phylumCount45_SILVA<- as.data.table(table(SILVA45_Full$Phylum)) #count by Phylum.
phylumCount45_SILVA<- phylumCount45_SILVA[order(phylumCount45_SILVA$N)]
phylumCount45_SILVA #V1 is the Phylum name, N is the count.
phylumCount68_SILVA<- as.data.table(table(SILVA68_Full$Phylum)) #count by Phylum.
phylumCount68_SILVA<- phylumCount68_SILVA[order(phylumCount68_SILVA$N)]
phylumCount68_SILVA #V1 is the Phylum name, N is the count.
#Get top Orders
topTaxa45_SILVA_Phy <- slice_tail(phylumCount45_SILVA, n=20) #get the bottom 20 counts (it's by ascending order)
topTaxa45_SILVA_Phy
topTaxa68_SILVA_Phy <- slice_tail(phylumCount68_SILVA,n=20)
topTaxa68_SILVA_Phy
#Green Genes:
#Sort out the counts of Orders
phylumCount45_GG<- as.data.table(table(GG45_Full$Phylum)) #count by Phylum.
phylumCount45_GG<- phylumCount45_GG[order(phylumCount45_GG$N)]
phylumCount45_GG #V1 is the Phylum name, N is the count.
phylumCount68_GG<- as.data.table(table(GG68_Full$Phylum)) #count by Phylum.
phylumCount68_GG<- phylumCount68_GG[order(phylumCount68_GG$N)]
phylumCount68_GG #V1 is the Phylum name, N is the count.
#Get top Orders
topTaxa45_GG_Phy <- slice_tail(phylumCount45_GG, n=20) #get the bottom 20 counts (it's by ascending order)
topTaxa45_GG_Phy
topTaxa68_GG_Phy <- slice_tail(phylumCount68_GG,n=20)
topTaxa68_GG_Phy
#RDP:
#Sort out the counts of Orders
phylumCount45_RDP<- as.data.table(table(RDP45_Full$Phylum)) #count by Phylum.
phylumCount45_RDP<- phylumCount45_RDP[order(phylumCount45_RDP$N)]
phylumCount45_RDP #V1 is the Phylum name, N is the count.
phylumCount68_RDP<- as.data.table(table(RDP68_Full$Phylum)) #count by Phylum.
phylumCount68_RDP<- phylumCount68_RDP[order(phylumCount68_RDP$N)]
phylumCount68_RDP #V1 is the Phylum name, N is the count.
#Get top Orders
topTaxa45_RDP_Phy <- slice_tail(phylumCount45_RDP, n=20) #get the bottom 20 counts (it's by ascending order)
topTaxa45_RDP_Phy
topTaxa68_GG_Phy <- slice_tail(phylumCount68_RDP,n=20)
topTaxa68_GG_Phy
#####Proportion plot for each sample with both primer, based on PHYLUM ######
#SILVA:
#Find top 20 orders and put them in a vector (used to filter)
top_SILVA45_Phy<- as.data.table(table(SILVA45_Full$Phylum)) #count by Phylum.
top_SILVA45_Phy<- top_SILVA45_Phy[order(top_SILVA45_Phy$N)]
top_SILVA45_Phy <- slice_tail(top_SILVA45_Phy, n=20)
top_SILVA45_Phy <- as.vector(tail(top_SILVA45_Phy$V1,20))
top_SILVA45_Phy #Vector containing top 20
top_SILVA68_Phy<- as.data.table(table(SILVA68_Full$Phylum)) #count by Phylum.
top_SILVA68_Phy<- top_SILVA68_Phy[order(top_SILVA68_Phy$N)]
top_SILVA68_Phy <- slice_tail(top_SILVA68_Phy, n=20)
top_SILVA68_Phy <- as.vector(tail(top_SILVA68_Phy$V1,20))
top_SILVA68_Phy #Vector containing top 20
top_GG45_Phy<- as.data.table(table(GG45_Full$Phylum)) #count by Phylum.
top_GG45_Phy<- top_GG45_Phy[order(top_GG45_Phy$N)]
top_GG45_Phy <- slice_tail(top_GG45_Phy, n=20)
top_GG45_Phy #Vector containing top 20
top_GG68_Phy<- as.data.table(table(GG68_Full$Phylum)) #count by Phylum.
top_GG68_Phy<- top_GG68_Phy[order(top_GG68_Phy$N)]
top_GG68_Phy <- slice_tail(top_GG68_Phy, n=20)
top_GG68_Phy <- as.vector(tail(top_GG68_Phy$V1,20))
top_GG68_Phy #Vector containing top 20
top_RDP45_Phy<- as.data.table(table(RDP45_Full$Phylum)) #count by Phylum.
top_RDP45_Phy<- top_RDP45_Phy[order(top_RDP45_Phy$N)]
top_RDP45_Phy <- slice_tail(top_RDP45_Phy, n=20)
top_RDP45_Phy <- as.vector(tail(top_RDP45_Phy$V1,20))
top_RDP45_Phy #Vector containing top 20
top_RDP68_Phy<- as.data.table(table(RDP68_Full$Phylum)) #count by Phylum.
top_RDP68_Phy<- top_RDP68_Phy[order(top_RDP68_Phy$N)]
top_RDP68_Phy <- slice_tail(top_RDP68_Phy, n=20)
top_RDP68_Phy <- as.vector(tail(top_RDP68_Phy$V1,20))
top_RDP68_Phy #Vector containing top 20
#Calculate proportion
# P_SIL_45<-top_SILVA45_Phy[,-1]
# totu<-t(P_SIL_45)
# x<-totu/rowSums(totu)
# x<-na.omit(x)
# propPhy_SIL_45<-t(x)
# propPhy_SIL_45 <- as.data.frame(propPhy_SIL_45)
# propPhy_SIL_45$Phyla <- top_SILVA45_Phy
#Filter results
top20_SILVA45_Phy <- SILVA45_Full %>% filter(Phylum == top_SILVA45_Phy) #Filter for only the ones with the names of the top 20 orders
top20_SILVA68_Phy <- SILVA68_Full %>% filter(Phylum == top_SILVA68_Phy) #Filter for only the ones with the names of the top 20 orders
top20_GG45_Phy <- GG45_Full %>% filter(Phylum == top_GG45_Phy) #Filter for only the ones with the names of the top 20 orders
top20_GG68_Phy <- GG68_Full %>% filter(Phylum == top_GG68_Phy) #Filter for only the ones with the names of the top 20 orders
top20_RDP45_Phy <- RDP45_Full %>% filter(Phylum == top_RDP45_Phy) #Filter for only the ones with the names of the top 20 orders
top20_RDP68_Phy <- RDP68_Full %>% filter(Phylum == top_RDP68_Phy) #Filter for only the ones with the names of the top 20 orders
colourAssign = c("Lentisphaerae"="darkviolet","Nitrospirae"="maroon3","Nanoarchaeaeota"="paleturquoise4","Armatimonadetes"="seagreen4","Gemmatimonadetes"="orangered2", "Chloroflexi"="orange3","Nitrospinae"="royalblue3","Patescibacteria"="violetred","Marinimicrobia (SAR406 clade)"="deepskyblue1","Firmicutes"="brown3", "Euryarchaeota"="darkcyan","Acidobacteria"="firebrick3","Verrucomicrobia"="gray46", "Thaumarchaeota"="mediumseagreen", " "="mediumpurple2", "Actinobacteria"="goldenrod1", "Planctomycetes"="orchid4", "Cyanobacteria"="darkslategrey", "Bacteroidetes"="mediumpurple1","Proteobacteria"="salmon1")
S45 <- ggplot(top20_SILVA45_Phy,aes(x=i.SAMPLE_NAME, y=Counts, fill=Phylum)) +
ggtitle("Top 20 Phyla from SILVA in samples sequenced by V4-V5 region")+ # for the main title
geom_bar(stat="identity", position="fill")+ scale_fill_manual(values=colourAssign)+theme_bw()+
theme(axis.text.x= element_text(angle = 45, hjust = 1, size=7)) +guides(fill=guide_legend(title="Order"))+ylab(label="Relative abundance")
S45
S68 <- ggplot(top20_SILVA68_Phy,aes(x=i.SAMPLE_NAME, y=Counts, fill=Phylum)) +
ggtitle("Top 20 Orders from SILVA in samples sequenced by V6-V8 region")+ # for the main title
geom_bar(stat="identity", position="fill")+ scale_fill_manual(values=colourAssign_phy)+theme_bw()+
theme(axis.text.x= element_text(angle = 45, hjust = 1, size=7)) +guides(fill=guide_legend(title="Order"))+ylab(label="Relative abundance")
S68
#Old method
#
# S45 <- ggplot(top20_SILVA45_Phy, aes(x = i.SAMPLE_NAME, y = Counts, fill = Phylum)) + geom_bar(position = "fill", stat = "identity")
# ggplot(top20_SILVA45_Phy, aes(fill=Counts, y=1, x=1)) +
# ggtitle("Top 20 Phyla from SILVA in samples sequenced by V4-V5 region")+ # for the main title
# geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
# S45
#
#
# S68 <- ggplot(top20_SILVA68_Phy, aes(x = Counts, y = i.SAMPLE_NAME, fill = Phylum)) + geom_bar(position = "fill", stat = "identity")
# ggplot(top20_SILVA68_Phy, aes(fill=Counts, y=1, x=1)) +
# ggtitle("Top 20 Orders from SILVA in samples sequenced by V6-V8 region")+ # for the main title
# geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
# S68
#
#
# GG45 <- ggplot(top20_GG45_Phy, aes(x = Counts, y = i.SAMPLE_NAME, fill = Phylum)) + geom_bar(position = "fill", stat = "identity")
# ggplot(top20_GG45_Phy, aes(fill=Counts, y=1, x=1)) +
# ggtitle("Top 20 Orders from GreenGenes in samples sequenced by V4-V5 region")+ # for the main title
# geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
# GG45
#
#
# GG68 <- ggplot(top20_GG68_Phy, aes(x = Counts, y = i.SAMPLE_NAME, fill = Phylum)) + geom_bar(position = "fill", stat = "identity")
# ggplot(top20_GG68_Phy, aes(fill=Counts, y=1, x=1)) +
# ggtitle("Top 20 Orders from GreenGenes in samples sequenced by V6-V8 region")+ # for the main title
# geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
# GG68
#
#
# RDP45 <- ggplot(top20_RDP45_Phy, aes(x = Counts, y = i.SAMPLE_NAME, fill = Phylum)) + geom_bar(position = "fill", stat = "identity")
# ggplot(top20_RDP45_Phy, aes(fill=Counts, y=1, x=1)) +
# ggtitle("Top 20 Orders from GreenGenes in samples sequenced by V6-V8 region")+ # for the main title
# geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
# RDP45
#
#
# RDP68 <- ggplot(top20_RDP68_Phy, aes(x = Counts, y = i.SAMPLE_NAME, fill = Phylum)) + geom_bar(position = "fill", stat = "identity")
# ggplot(top20_RDP68_Phy, aes(fill=Counts, y=1, x=1)) +
# ggtitle("Top 20 Orders from GreenGenes in samples sequenced by V6-V8 region")+ # for the main title
# geom_bar(position="fill", stat="identity") + expand_limits(y = 9, x=-9) # or some other arbitrarily large number
# RDP68
colourAssign_phy = c("Lentisphaerae"="darkviolet","Nitrospirae"="maroon3","Nanoarchaeaeota"="paleturquoise4","Armatimonadetes"="seagreen4","Gemmatimonadetes"="orangered2", "Chloroflexi"="orange3","Nitrospinae"="royalblue3","Patescibacteria"="violetred","Marinimicrobia (SAR406 clade)"="deepskyblue1","Firmicutes"="brown3", "Euryarchaeota"="darkcyan","Acidobacteria"="firebrick3","Verrucomicrobia"="gray46", "Thaumarchaeota"="mediumseagreen", " "="mediumpurple2", "Actinobacteria"="goldenrod1", "Planctomycetes"="orchid4", "Cyanobacteria"="darkslategrey", "Bacteroidetes"="mediumpurple1","Proteobacteria"="salmon1", "Chlamydiae"="linen", "Dependentiae"="darkturquoise", "Epsilonbacteraeota"="wheat2")
#Check the amount that cannot be identified in the different databases
#Sort out the counts of Phyla
phylumCount45_GG<- as.data.table(table(GG45_Full$Phylum)) #count by Phylum.
phylumCount45_GG<- phylumCount45_GG[order(phylumCount45_GG$N)]
phylumCount45_GG #V1 is the Phylum name, N is the count.
sumPhyCount45_GG <- sum(phylumCount45_GG$N) #Sum all the counts
undefProp45_GG <- 19378/sumPhyCount45_GG #Value manually found by looking at output
undefProp45_GG #Result: 98.67604% of phyla are not defined with V4-V5k primer.
#Sort out the counts of Phyla
phylumCount68_GG<- as.data.table(table(GG68_Full$Phylum)) #count by Phylum.
phylumCount68_GG<- phylumCount68_GG[order(phylumCount68_GG$N)]
phylumCount68_GG #V1 is the Phylum name, N is the count.
sumPhyCount68_GG <- sum(phylumCount68_GG$N) #Sum all the counts
undefProp68_GG <- 9846/sumPhyCount68_GG #Value manually found by looking at output
undefProp68_GG #Result: 98.83558% of phyla are not defined with V6-V8 primer.
#Abundance of Chloroplasts and SAR11
#SILVA
(SILVA45_Full)
(SILVA68_Full)
#RDP
(RDP45_Full)
(RDP68_Full)
#GreenGenes
(GG45_Full)
(GG68_Full)
### Chloroplasts ###
#V4 V5
chloro_SILVA45 <- SILVA45_Full %>% filter(Order == "Chloroplast") #Filter for only chloroplasts
chloroSum45_SILVA <- sum(chloro_SILVA45$Counts)
chloroSum45_SILVA #this is the number of sequences associated with chloroplasts by V4V5
S45 <- ggplot(chloro_SILVA45, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
S45
chloro_RDP45 <- RDP45_Full %>% filter(Order == "Chloroplast") #Filter for only chloroplasts
chloroSum45_RDP <- sum(chloro_RDP45$Counts)
chloroSum45_RDP #this is the number of sequences associated with chloroplasts by V4V5
R45 <- ggplot(chloro_RDP45, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
R45
### CHANGED GG TO CLASS
chloro_GG45 <- GG45_Full %>% filter(Class == "Chloroplast") #Filter for only chloroplasts
chloroSum45_GG <- sum(chloro_GG45$Counts)
chloroSum45_GG #this is the number of sequences associated with chloroplasts by V4V5
G45 <- ggplot(chloro_GG45, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
G45
#V6 V8
chloro_RDP68 <- RDP68_Full %>% filter(Order == "Chloroplast") #Filter for only chloroplasts
chloroSum68_RDP <- sum(chloro_RDP68$Counts)
chloroSum68_RDP #this is the number of sequences associated with chloroplasts by V4V5
R68 <- ggplot(chloro_RDP68, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
R68
### CHANGED GG TO CLASS
chloro_GG68 <- GG68_Full %>% filter(Class == "Chloroplast") #Filter for only chloroplasts
chloroSum68_GG <- sum(chloro_GG68$Counts)
chloroSum68_GG #this is the number of sequences associated with chloroplasts by V4V5
G68 <- ggplot(chloro_GG68, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
G68
chloro_SILVA68 <- SILVA68_Full %>% filter(Order == "Chloroplast") #Filter for only chloroplasts
chloroSum68_SILVA <- sum(chloro_SILVA68$Counts)
chloroSum68_SILVA #this is the number of sequences associated with chloroplasts by V4V5
S68 <- ggplot(chloro_SILVA68, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
S68
### SAR11 ###
#V4 V5
SAR_SILVA45 <- SILVA45_Full %>% filter(Order == "SAR11 clade") #Filter for only SARplasts
SARSum45_SILVA <- sum(SAR_SILVA45$Counts)
SARSum45_SILVA #this is the number of sequences associated with SARplasts by V4V5
S45 <- ggplot(SAR_SILVA45, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
S45
SAR_RDP45 <- RDP45_Full %>% filter(Order == "SAR11") #Filter for only SARplasts
SARSum45_RDP <- sum(SAR_RDP45$Counts)
SARSum45_RDP #this is the number of sequences associated with SARplasts by V4V5
R45 <- ggplot(SAR_RDP45, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
R45
SAR_GG45 <- GG45_Full %>% filter(Order == "SAR11") #Filter for only SARplasts
SARSum45_GG <- sum(SAR_GG45$Counts)
SARSum45_GG #this is the number of sequences associated with SARplasts by V4V5
G45 <- ggplot(SAR_GG45, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
G45
#V6 V8
SAR_RDP68 <- RDP68_Full %>% filter(Order == "SAR11") #Filter for only SARplasts
SARSum68_RDP <- sum(SAR_RDP68$Counts)
SARSum68_RDP #this is the number of sequences associated with SARplasts by V4V5
R68 <- ggplot(SAR_RDP68, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
R68
SAR_GG68 <- GG68_Full %>% filter(Order == "SAR11") #Filter for only SARplasts
SARSum68_GG <- sum(SAR_GG68$Counts)
SARSum68_GG #this is the number of sequences associated with SARplasts by V4V5
G68 <- ggplot(SAR_GG68, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
G68
SAR_SILVA68 <- SILVA68_Full %>% filter(Order == "SAR11 clade") #Filter for only SARplasts
SARSum68_SILVA <- sum(SAR_SILVA68$Counts)
SARSum68_SILVA #this is the number of sequences associated with SARplasts by V4V5
S68 <- ggplot(SAR_SILVA68, aes(x = Counts, y = i.SAMPLE_NAME)) + geom_bar(stat = "identity")
geom_bar(stat="identity",position = position_dodge(width=1.5))
S68
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCiNBYnVuZGFuY2UgZ3JhcGhzDQpgYGANCg0KLS0tDQp0aXRsZTogIkRhdGFiYXNlIE5NRFMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KYGBge3J9DQojTG9hZCBwYWNrYWdlcw0KDQpsaWJyYXJ5KCJ0aWR5dmVyc2UiKQ0KbGlicmFyeSgiZGFkYTIiKQ0KbGlicmFyeSgiYmlvbWZvcm1hdCIpDQpsaWJyYXJ5KCd2ZWdhbicpDQpsaWJyYXJ5KCdyZWFkcicpDQpsaWJyYXJ5KCJkcGx5ciIpICAgICAjIFRvIG1hbmlwdWxhdGUgZGF0YWZyYW1lcw0KbGlicmFyeSgicmVhZHhsIikgICAgIyBUbyByZWFkIEV4Y2VsIGZpbGVzIGludG8gUg0KbGlicmFyeSgiZ2dwbG90MiIpICAgIyBmb3IgaGlnaCBxdWFsaXR5IGdyYXBoaWNzDQpsaWJyYXJ5KCJCaW9jTWFuYWdlciIpDQpsaWJyYXJ5KCJwaHlsb3NlcSIpICAgDQpsaWJyYXJ5KCJ0aWR5ciIpDQpsaWJyYXJ5KCJkYXRhLnRhYmxlIikNCmxpYnJhcnkoImVzcXVpc3NlIikNCg0KI0NvbG91ciBwYWxldHRlcw0KI2luc3RhbGwucGFja2FnZXMoImVzcXVpc3NlIikNCmxpYnJhcnkod2VzYW5kZXJzb24pDQpsaWJyYXJ5KHZpcmlkaXMpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoZ2dzY2kpDQpgYGANCg0KYGBge3J9DQojTG9hZCBpbiBEYXRhLCBtZXJnZSB0YWJsZXMNCg0KIyMjcmVhZCBpbiBiaW9tLXRheG9ub215IGZvciBTSUxWQSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiNTSUxWQQ0KdGF4b25vbXk0NV9TSUxWQSA8LSByZWFkLmNzdigiRzovRGVza3RvcC9Gb2xkZXJzL0VkdS8yXSBFQVMvVGhlc2lzL1JlYWxfQ29udGVudC9EYXRhX0ZpbGVzL1Y0VjUvVjRWNV9TSUxWQV90YXhvbm9teS5jc3YiKQ0KdGF4b25vbXk2OF9TSUxWQSA8LSByZWFkLmNzdigiRzovRGVza3RvcC9Gb2xkZXJzL0VkdS8yXSBFQVMvVGhlc2lzL1JlYWxfQ29udGVudC9EYXRhX0ZpbGVzL1Y2VjgvdGF4b25vbXlfU0lMVkFfVjZWOC5jc3YiKQ0KDQojUkRQDQp0YXhvbm9teTQ1X1JEUCA8LSByZWFkLmNzdigiRzovRGVza3RvcC9Gb2xkZXJzL0VkdS8yXSBFQVMvVGhlc2lzL1JlYWxfQ29udGVudC9EYXRhX0ZpbGVzL1Y0VjUvdGF4b25vbXlfUkRQX1Y0VjUuY3N2IikNCnRheG9ub215NjhfUkRQIDwtIHJlYWQuY3N2KCJHOi9EZXNrdG9wL0ZvbGRlcnMvRWR1LzJdIEVBUy9UaGVzaXMvUmVhbF9Db250ZW50L0RhdGFfRmlsZXMvVjZWOC90YXhvbm9teV9SRFBfVjZWOC5jc3YiKQ0KDQojR3JlZW5HZW5lcw0KdGF4b25vbXk0NV9HRyA8LSByZWFkLmNzdigiRzovRGVza3RvcC9Gb2xkZXJzL0VkdS8yXSBFQVMvVGhlc2lzL1JlYWxfQ29udGVudC9EYXRhX0ZpbGVzL1Y0VjUvdGF4b25vbXlfZ3JlZW5nZW5lc19WNFY1LmNzdiIpDQp0YXhvbm9teTY4X0dHIDwtIHJlYWQuY3N2KCJHOi9EZXNrdG9wL0ZvbGRlcnMvRWR1LzJdIEVBUy9UaGVzaXMvUmVhbF9Db250ZW50L0RhdGFfRmlsZXMvVjZWOC90YXhvbm9teV9ncmVlbmdlbmVzX1Y2VjguY3N2IikNCg0KdGF4b25vbXk0NV9TSUxWQTwtYXMuZGF0YS50YWJsZSh0YXhvbm9teTQ1X1NJTFZBKQ0KdGF4b25vbXk2OF9TSUxWQTwtYXMuZGF0YS50YWJsZSh0YXhvbm9teTY4X1NJTFZBKQ0KdGF4b25vbXk0NV9SRFA8LWFzLmRhdGEudGFibGUodGF4b25vbXk0NV9SRFApDQp0YXhvbm9teTY4X1JEUDwtYXMuZGF0YS50YWJsZSh0YXhvbm9teTY4X1JEUCkNCnRheG9ub215NDVfR0c8LWFzLmRhdGEudGFibGUodGF4b25vbXk0NV9HRykNCnRheG9ub215NjhfR0c8LWFzLmRhdGEudGFibGUodGF4b25vbXk2OF9HRykNCg0KDQojIyNyZWFkIGluIG90dSB0YWJsZXMgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0Kb3R1NDU8LSByZWFkLmNzdigiRzovRGVza3RvcC9Gb2xkZXJzL0VkdS8yXSBFQVMvVGhlc2lzL1JlYWxfQ29udGVudC9EYXRhX0ZpbGVzL1Y0VjUvVjRWNV9fQVNWX3RhYmxlLmNzdiIsIGhlYWRlciA9IFQpICMscm93Lm5hbWVzPTENCm90dTY4PC0gcmVhZC5jc3YoIkc6L0Rlc2t0b3AvRm9sZGVycy9FZHUvMl0gRUFTL1RoZXNpcy9SZWFsX0NvbnRlbnQvRGF0YV9GaWxlcy9WNlY4L1Y2VjhfX0FTVl90YWJsZS5jc3YiLCBoZWFkZXIgPSBUKQ0KaGVhZChvdHU0NSkgDQpoZWFkKG90dTY4KQ0KDQojQ29udmVydCB0byBsb25nIGZvcm1hdA0Kb3R1X2xvbmc0NTwtZ2F0aGVyKG90dTQ1LCBTYW1wbGUsIENvdW50cywgIlgzIjoiWDE1NyIpICNkYXNoZXMgZ290IGNoYW5nZWQgdG8gZG90cyBmb3Igc29tZSByZWFzb24NCm90dV9sb25nNjg8LWdhdGhlcihvdHU2OCwgU2FtcGxlLCBDb3VudHMsICJvXzEyMiI6Im9fODMiKSAjZGFzaGVzIGdvdCBjaGFuZ2VkIHRvIGRvdHMgZm9yIHNvbWUgcmVhc29uDQoNCiNtYWtlIGEgZGF0YS5UYWJsZQ0Kb3R1X2xvbmc0NTwtYXMuZGF0YS50YWJsZShvdHVfbG9uZzQ1KQ0Kb3R1X2xvbmc2ODwtYXMuZGF0YS50YWJsZShvdHVfbG9uZzY4KQ0Kb3R1X2xvbmc0NQ0Kb3R1X2xvbmc2OA0KDQojIyNyZWFkIGluIG1ldGFkYXRhIGZpbGUgICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQptZXRhRDQ1PC1yZWFkLmNzdigiRzovRGVza3RvcC9Gb2xkZXJzL0VkdS8yXSBFQVMvVGhlc2lzL1JlYWxfQ29udGVudC9EYXRhX0ZpbGVzL1Y0VjUvbWV0YWRhdGFfMTZTX1Y0VjVfam9uZXNTb3VuZDIwMTkudHh0Iiwgc2VwID0gIiIpDQptZXRhRDQ1PC1hcy5kYXRhLnRhYmxlKG1ldGFENDUpDQptZXRhRDQ1JFNhbXBsZTwtYXMuY2hhcmFjdGVyKG1ldGFENDUkU2FtcGxlKQ0KbWV0YUQ0NQ0KDQptZXRhRDY4PC1yZWFkLmNzdigiRzovRGVza3RvcC9Gb2xkZXJzL0VkdS8yXSBFQVMvVGhlc2lzL1JlYWxfQ29udGVudC9EYXRhX0ZpbGVzL1Y2VjgvbWV0YWRhdGFfMTZTX1Y2Vjhfam9uZXNTb3VuZDIwMTkudHh0Iiwgc2VwID0gIiIpDQptZXRhRDY4PC1hcy5kYXRhLnRhYmxlKG1ldGFENjgpDQptZXRhRDY4JFNhbXBsZTwtYXMuY2hhcmFjdGVyKG1ldGFENjgkU2FtcGxlKQ0KbWV0YUQ2OA0KDQoNCiMjIyBNZXJnZSBkYXRhIHRhYmxlcyAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyBmaXJzdCBzZXQgdGhlIGtleXMgdG8gdGhlIGNvbW1vbiBjb2x1bW46DQpzZXRrZXkob3R1X2xvbmc2OCxTYW1wbGUpDQpzZXRrZXkobWV0YUQ2OCxTYW1wbGUpIA0Kc2V0a2V5KG90dV9sb25nNDUsU2FtcGxlKQ0Kc2V0a2V5KG1ldGFENDUsU2FtcGxlKSANCg0KIyBqb2luIHRoZSB0YWJsZXMNCk9UVV9NZXRhX01lcmdlXzQ1IDwtIG1lcmdlKG90dV9sb25nNDUsbWV0YUQ0NSxieT0iU2FtcGxlIikNCk9UVV9NZXRhX01lcmdlXzQ1DQpPVFVfTWV0YV9NZXJnZV82OCA8LSBtZXJnZShvdHVfbG9uZzY4LG1ldGFENjgsYnk9IlNhbXBsZSIpDQpPVFVfTWV0YV9NZXJnZV82OA0KDQojc2V0IGtleSBvZiBPVFVfTWV0YV9NZXJnZV80NSBhcyB0aGUgT1RVSUQgdG8gam9pbiB0aGUgdGF4b25vbXkgdGFibGUNCnNldGtleShPVFVfTWV0YV9NZXJnZV80NSxPVFVJRCkNCnNldGtleSh0YXhvbm9teTQ1LE9UVUlEKQ0Kc2V0a2V5KE9UVV9NZXRhX01lcmdlXzY4LE9UVUlEKQ0Kc2V0a2V5KHRheG9ub215NjgsT1RVSUQpDQoNCiNtZXJnZSBTSUxWQQ0KU0lMVkFfNDVfTWVyZ2VkIDwtIG1lcmdlKE9UVV9NZXRhX01lcmdlXzQ1LHRheG9ub215NDVfU0lMVkEpDQpzZXRrZXkoU0lMVkFfNDVfTWVyZ2VkLCBTYW1wbGUpDQpTSUxWQV82OF9NZXJnZWQgPC0gbWVyZ2UoT1RVX01ldGFfTWVyZ2VfNjgsdGF4b25vbXk2OF9TSUxWQSkNCnNldGtleShTSUxWQV82OF9NZXJnZWQsIFNhbXBsZSkNCg0KI21lcmdlIFJEUA0KdGF4b25vbXk0NV9SRFANClJEUF80NV9NZXJnZWQgPC0gbWVyZ2UoT1RVX01ldGFfTWVyZ2VfNDUsdGF4b25vbXk0NV9SRFApDQpzZXRrZXkoUkRQXzQ1X01lcmdlZCwgU2FtcGxlKQ0KUkRQXzY4X01lcmdlZCA8LSBtZXJnZShPVFVfTWV0YV9NZXJnZV82OCx0YXhvbm9teTY4X1JEUCkNCnNldGtleShSRFBfNjhfTWVyZ2VkLCBTYW1wbGUpDQoNCiNtZXJnZSBHRw0KR0dfNDVfTWVyZ2VkIDwtIG1lcmdlKE9UVV9NZXRhX01lcmdlXzQ1LHRheG9ub215NDVfR0cpDQpzZXRrZXkoR0dfNDVfTWVyZ2VkLCBTYW1wbGUpDQpHR182OF9NZXJnZWQgPC0gbWVyZ2UoT1RVX01ldGFfTWVyZ2VfNjgsdGF4b25vbXk2OF9HRykNCnNldGtleShHR182OF9NZXJnZWQsIFNhbXBsZSkNCg0KI0Zvcm1hdCBieSBtZXRhZGF0YQ0KI1NJTFZBDQpTSUxWQTQ1X0Z1bGwgPC0gbWV0YUQ0NVtTSUxWQV80NV9NZXJnZWRdDQooU0lMVkE0NV9GdWxsKQ0KU0lMVkE2OF9GdWxsIDwtIG1ldGFENjhbU0lMVkFfNjhfTWVyZ2VkXQ0KKFNJTFZBNjhfRnVsbCkNCiNSRFANClJEUDQ1X0Z1bGwgPC0gbWV0YUQ0NVtSRFBfNDVfTWVyZ2VkXQ0KKFJEUDQ1X0Z1bGwpDQpSRFA2OF9GdWxsIDwtIG1ldGFENjhbUkRQXzY4X01lcmdlZF0NCihSRFA2OF9GdWxsKQ0KI0dyZWVuR2VuZXMNCkdHNDVfRnVsbCA8LSBtZXRhRDQ1W0dHXzQ1X01lcmdlZF0NCihHRzQ1X0Z1bGwpDQpHRzY4X0Z1bGwgPC0gbWV0YUQ2OFtHR182OF9NZXJnZWRdDQooR0c2OF9GdWxsKQ0KDQoNCg0KDQpTSUxWQV9PVFVfVGF4YTQ1IDwtIG1lcmdlKG90dTQ1LHRheG9ub215NDVfU0lMVkEpDQpTSUxWQV9PVFVfVGF4YTQ1DQpgYGANCmBgYHtyfQ0KI0NvdW50IGJhY3RlcmlhbCBvcmRlcnMNCg0KYmFjdGVyaWFsX29yZGVyX1NJTFZBNDUgPC0gdGF4b25vbXk0NV9TSUxWQSAlPiUgZmlsdGVyKChLaW5nZG9tID09ICJCYWN0ZXJpYSIpICYgKE9yZGVyICE9ICIiKSkNCmJhY3RlcmlhbF9vcmRlcl9TSUxWQTQ1IDwtIGRpc3RpbmN0KGJhY3RlcmlhbF9vcmRlcl9TSUxWQTQ1LCBPcmRlcikNCiNFeGFjdGx5IDIzMCB1bmlxdWUgYmFjdGVyaWFsIG9yZGVycyB3ZXJlIGZvdW5kDQoNCmJhY3RlcmlhbF9vcmRlcl9TSUxWQTY4IDwtIHRheG9ub215NjhfU0lMVkEgJT4lIGZpbHRlcigoS2luZ2RvbSA9PSAiQmFjdGVyaWEiKSAmIChPcmRlciAhPSAiIikpDQpiYWN0ZXJpYWxfb3JkZXJfU0lMVkE2OCA8LSBkaXN0aW5jdChiYWN0ZXJpYWxfb3JkZXJfU0lMVkE2OCwgT3JkZXIpDQojMTk1IHVuaXF1ZSBiYWN0ZXJpYWwgb3JkZXJzIHdlcmUgZm91bmQNCg0KYmFjdGVyaWFsX29yZGVyX1JEUDQ1IDwtIHRheG9ub215NDVfUkRQICU+JSBmaWx0ZXIoKEtpbmdkb20gPT0gIkJhY3RlcmlhIikgJiAoT3JkZXIgIT0gIiIpKQ0KYmFjdGVyaWFsX29yZGVyX1JEUDQ1IDwtIGRpc3RpbmN0KGJhY3RlcmlhbF9vcmRlcl9SRFA0NSwgT3JkZXIpDQojRXhhY3RseSAxMDMgdW5pcXVlIGJhY3RlcmlhbCBvcmRlcnMgd2VyZSBmb3VuZA0KDQpiYWN0ZXJpYWxfb3JkZXJfUkRQNjggPC0gdGF4b25vbXk2OF9SRFAgJT4lIGZpbHRlcigoS2luZ2RvbSA9PSAiQmFjdGVyaWEiKSAmIChPcmRlciAhPSAiIikpDQpiYWN0ZXJpYWxfb3JkZXJfUkRQNjggPC0gZGlzdGluY3QoYmFjdGVyaWFsX29yZGVyX1JEUDY4LCBPcmRlcikNCiMxMDMgdW5pcXVlIGJhY3RlcmlhbCBvcmRlcnMgd2VyZSBmb3VuZA0KDQoNCg0KIyMjQXJjaGFlYWwgb3JkZXJzDQoNCmFyY2hhZWFsX29yZGVyX1NJTFZBNDUgPC0gdGF4b25vbXk0NV9TSUxWQSAlPiUgZmlsdGVyKChLaW5nZG9tID09ICJBcmNoYWVhIikgJiAoT3JkZXIgIT0gIiIpKQ0KYXJjaGFlYWxfb3JkZXJfU0lMVkE0NSA8LSBkaXN0aW5jdChhcmNoYWVhbF9vcmRlcl9TSUxWQTQ1LCBPcmRlcikNCmFyY2hhZWFsX29yZGVyX1NJTFZBNDUNCg0KYXJjaGFlYWxfb3JkZXJfU0lMVkE2OCA8LSB0YXhvbm9teTY4X1NJTFZBICU+JSBmaWx0ZXIoKEtpbmdkb20gPT0gIkFyY2hhZWEiKSAmIChPcmRlciAhPSAiIikpDQphcmNoYWVhbF9vcmRlcl9TSUxWQTY4IDwtIGRpc3RpbmN0KGFyY2hhZWFsX29yZGVyX1NJTFZBNjgsIE9yZGVyKQ0KYXJjaGFlYWxfb3JkZXJfU0lMVkE2OA0KDQphcmNoYWVhbF9vcmRlcl9SRFA0NSA8LSB0YXhvbm9teTQ1X1JEUCAlPiUgZmlsdGVyKChLaW5nZG9tID09ICJBcmNoYWVhIikgJiAoT3JkZXIgIT0gIiIpKQ0KYXJjaGFlYWxfb3JkZXJfUkRQNDUgPC0gZGlzdGluY3QoYXJjaGFlYWxfb3JkZXJfUkRQNDUsIE9yZGVyKQ0KYXJjaGFlYWxfb3JkZXJfUkRQNDUNCg0KYXJjaGFlYWxfb3JkZXJfUkRQNjggPC0gdGF4b25vbXk2OF9SRFAgJT4lIGZpbHRlcigoS2luZ2RvbSA9PSAiQXJjaGFlYSIpICYgKE9yZGVyICE9ICIiKSkNCmFyY2hhZWFsX29yZGVyX1JEUDY4IDwtIGRpc3RpbmN0KGFyY2hhZWFsX29yZGVyX1JEUDY4LCBPcmRlcikNCmFyY2hhZWFsX29yZGVyX1JEUDY4DQoNCg0KDQojIyNDaGxvcm9wbGFzdA0KI0NobG9yb3BsYXN0IEFTVnMuIE5vdCB1bmlxdWUsIE5PVCBPUkRFUlMsIGp1c3QgQVNWcyBkZXRlY3RlZA0KDQpjaGxvcm9fb3JkZXJfU0lMVkE0NSA8LSB0YXhvbm9teTQ1X1NJTFZBICU+JSBmaWx0ZXIoKE9yZGVyID09ICJDaGxvcm9wbGFzdCIpICYgKE9yZGVyICE9ICIiKSkNCmNobG9yb19vcmRlcl9TSUxWQTQ1DQoNCmNobG9yb19vcmRlcl9TSUxWQTY4IDwtIHRheG9ub215NjhfU0lMVkEgJT4lIGZpbHRlcigoT3JkZXIgPT0gIkNobG9yb3BsYXN0IikgJiAoT3JkZXIgIT0gIiIpKQ0KY2hsb3JvX29yZGVyX1NJTFZBNjgNCg0KY2hsb3JvX29yZGVyX1JEUDQ1IDwtIHRheG9ub215NDVfUkRQICU+JSBmaWx0ZXIoKE9yZGVyID09ICJDaGxvcm9wbGFzdCIpICYgKE9yZGVyICE9ICIiKSkNCmNobG9yb19vcmRlcl9SRFA0NQ0KDQpjaGxvcm9fb3JkZXJfUkRQNjggPC0gdGF4b25vbXk2OF9SRFAgJT4lIGZpbHRlcigoT3JkZXIgPT0gIkNobG9yb3BsYXN0IikgJiAoT3JkZXIgIT0gIiIpKQ0KY2hsb3JvX29yZGVyX1JEUDY4DQoNCg0KDQoNCg0KDQpgYGANCg0KDQoNCmBgYHtyfQ0KI1N0YXRpc3RpY2FsIGRpZmZlcmVuY2VzIGluIE9UVSB0YWJsZSBieSBwcmltZXIgcmVnaW9uDQoNCiNLcnVza2FsIFdhbGxpcyB0ZXN0Og0KI2h0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvd2lraS9rcnVza2FsLXdhbGxpcy10ZXN0LWluLXINCiNodHRwczovL3N0YXRzLnN0YWNrZXhjaGFuZ2UuY29tL3F1ZXN0aW9ucy80NDMzMjkva3J1c2thbC13YWxsaXMtdGVzdC1mb3ItbXVsdGlwbGUtdmFyaWFibGVzLWRpZmZlcmVudC1pbi1yLWFuZC1weXRob24NCiAgDQoja3J1c2thbC50ZXN0KFByaW1lciB+IG90dV9mdWxsWywxXSwgZGF0YSA9IG90dV9mdWxsKSAjIyNUZXN0IG9uZSBieSBvbmUNCg0Kb3R1X2Z1bGwgPC0gbWVyZ2UoYnkgPSAiT1RVSUQiLCBvdHU0NSwgb3R1NjgsIGFsbC54ID0gVFJVRSkNCg0Ka3J1c2thbC50ZXN0KG90dV9mdWxsWzI6MjhdLCBvdHVfZnVsbFsyOTo1NV0sIGRhdGEgPSBvdHVfZnVsbCkgI1Rlc3QgcmFuZ2Ugb2YgY29sdW1ucyBhZ2FpbnN0IGVhY2ggb3RoZXINCg0KYGBgDQoNCg0KDQoNCg0KDQpgYGB7cn0NCiNUb3AgMjAgb3JkZXJzIG9mIGVhY2ggZGF0YWJhc2UgYW5kIGVhY2ggcHJpbWVyIGFzIHRhYmxlcw0KDQoNCiNTSUxWQToNCg0KI1NvcnQgb3V0IHRoZSBjb3VudHMgb2YgT3JkZXJzDQpvcmRlckNvdW50NDVfU0lMVkE8LSBhcy5kYXRhLnRhYmxlKHRhYmxlKFNJTFZBNDVfRnVsbCRPcmRlcikpICNjb3VudCBieSBPcmRlci4NCm9yZGVyQ291bnQ0NV9TSUxWQTwtIG9yZGVyQ291bnQ0NV9TSUxWQVtvcmRlcihvcmRlckNvdW50NDVfU0lMVkEkTildDQpvcmRlckNvdW50NDVfU0lMVkEgI1YxIGlzIHRoZSBPcmRlciBuYW1lLCBOIGlzIHRoZSBjb3VudC4NCg0Kb3JkZXJDb3VudDY4X1NJTFZBPC0gYXMuZGF0YS50YWJsZSh0YWJsZShTSUxWQTY4X0Z1bGwkT3JkZXIpKSAjY291bnQgYnkgT3JkZXIuDQpvcmRlckNvdW50NjhfU0lMVkE8LSBvcmRlckNvdW50NjhfU0lMVkFbb3JkZXIob3JkZXJDb3VudDY4X1NJTFZBJE4pXQ0Kb3JkZXJDb3VudDY4X1NJTFZBICNWMSBpcyB0aGUgT3JkZXIgbmFtZSwgTiBpcyB0aGUgY291bnQuDQoNCiNDT01CSU5FRCBWQUxVRVMNCm9yZGVyQ291bnRCb3RoX1NJTFZBIDwtIG1lcmdlKG9yZGVyQ291bnQ0NV9TSUxWQSwgb3JkZXJDb3VudDY4X1NJTFZBLCBieSA9ICJWMSIgKQ0Kb3JkZXJDb3VudEJvdGhfU0lMVkEkdG90YWxfQVNWX2NvdW50IDwtIG9yZGVyQ291bnRCb3RoX1NJTFZBJE4ueCArIG9yZGVyQ291bnRCb3RoX1NJTFZBJE4ueQ0Kb3JkZXJDb3VudEJvdGhfU0lMVkE8LSBvcmRlckNvdW50Qm90aF9TSUxWQVtvcmRlcihvcmRlckNvdW50Qm90aF9TSUxWQSR0b3RhbF9BU1ZfY291bnQpXQ0KDQoNCiNHZXQgdG9wIE9yZGVycw0KdG9wVGF4YTQ1X1NJTFZBIDwtIHNsaWNlX3RhaWwob3JkZXJDb3VudDQ1X1NJTFZBLCBuPTIwKSAjZ2V0IHRoZSBib3R0b20gMjAgY291bnRzIChpdCdzIGJ5IGFzY2VuZGluZyBvcmRlcikNCnRvcFRheGE0NV9TSUxWQQ0KDQp0b3BUYXhhNjhfU0lMVkEgPC0gc2xpY2VfdGFpbChvcmRlckNvdW50NjhfU0lMVkEsbj0yMCkNCnRvcFRheGE2OF9TSUxWQQ0KDQp0b3BUYXhhQm90aF9TSUxWQSA8LSBzbGljZV90YWlsKG9yZGVyQ291bnRCb3RoX1NJTFZBLG49MjApDQp0b3BUYXhhQm90aF9TSUxWQQ0KDQp0b3BUYXhhQm90aF9TSUxWQV9uYW1ldmVjIDwtIHRvcFRheGFCb3RoX1NJTFZBJFYxDQoNCg0KDQojR3JlZW4gR2VuZXM6DQoNCiNTb3J0IG91dCB0aGUgY291bnRzIG9mIE9yZGVycw0Kb3JkZXJDb3VudDQ1X0dHPC0gYXMuZGF0YS50YWJsZSh0YWJsZShHRzQ1X0Z1bGwkT3JkZXIpKSAjY291bnQgYnkgT3JkZXIuDQpvcmRlckNvdW50NDVfR0c8LSBvcmRlckNvdW50NDVfR0dbb3JkZXIob3JkZXJDb3VudDQ1X0dHJE4pXQ0Kb3JkZXJDb3VudDQ1X0dHICNWMSBpcyB0aGUgT3JkZXIgbmFtZSwgTiBpcyB0aGUgY291bnQuDQoNCg0Kb3JkZXJDb3VudDY4X0dHPC0gYXMuZGF0YS50YWJsZSh0YWJsZShHRzY4X0Z1bGwkT3JkZXIpKSAjY291bnQgYnkgT3JkZXIuDQpvcmRlckNvdW50NjhfR0c8LSBvcmRlckNvdW50NjhfR0dbb3JkZXIob3JkZXJDb3VudDY4X0dHJE4pXQ0Kb3JkZXJDb3VudDY4X0dHICNWMSBpcyB0aGUgT3JkZXIgbmFtZSwgTiBpcyB0aGUgY291bnQuDQoNCiNHZXQgdG9wIE9yZGVycw0KdG9wVGF4YTQ1X0dHIDwtIHNsaWNlX3RhaWwob3JkZXJDb3VudDQ1X0dHLCBuPTIwKSAjZ2V0IHRoZSBib3R0b20gMjAgY291bnRzIChpdCdzIGJ5IGFzY2VuZGluZyBvcmRlcikNCnRvcFRheGE0NV9HRw0KDQp0b3BUYXhhNjhfR0cgPC0gc2xpY2VfdGFpbChvcmRlckNvdW50NjhfR0csbj0yMCkNCnRvcFRheGE2OF9HRw0KDQoNCiNSRFA6DQoNCiNTb3J0IG91dCB0aGUgY291bnRzIG9mIE9yZGVycw0Kb3JkZXJDb3VudDQ1X1JEUDwtIGFzLmRhdGEudGFibGUodGFibGUoUkRQNDVfRnVsbCRPcmRlcikpICNjb3VudCBieSBPcmRlci4NCm9yZGVyQ291bnQ0NV9SRFA8LSBvcmRlckNvdW50NDVfUkRQW29yZGVyKG9yZGVyQ291bnQ0NV9SRFAkTildDQpvcmRlckNvdW50NDVfUkRQICNWMSBpcyB0aGUgT3JkZXIgbmFtZSwgTiBpcyB0aGUgY291bnQuDQoNCm9yZGVyQ291bnQ2OF9SRFA8LSBhcy5kYXRhLnRhYmxlKHRhYmxlKFJEUDY4X0Z1bGwkT3JkZXIpKSAjY291bnQgYnkgT3JkZXIuDQpvcmRlckNvdW50NjhfUkRQPC0gb3JkZXJDb3VudDY4X1JEUFtvcmRlcihvcmRlckNvdW50NjhfUkRQJE4pXQ0Kb3JkZXJDb3VudDY4X1JEUCAjVjEgaXMgdGhlIE9yZGVyIG5hbWUsIE4gaXMgdGhlIGNvdW50Lg0KDQojR2V0IHRvcCBPcmRlcnMNCnRvcFRheGE0NV9SRFAgPC0gc2xpY2VfdGFpbChvcmRlckNvdW50NDVfUkRQLCBuPTIwKSAjZ2V0IHRoZSBib3R0b20gMjAgY291bnRzIChpdCdzIGJ5IGFzY2VuZGluZyBvcmRlcikNCnRvcFRheGE0NV9SRFANCg0KdG9wVGF4YTY4X1JEUCA8LSBzbGljZV90YWlsKG9yZGVyQ291bnQ2OF9SRFAsbj0yMCkNCnRvcFRheGE2OF9SRFANCg0KDQpgYGANCg0KDQoNCmBgYHtyfQ0KIyMjIyNQcm9wb3J0aW9uIHBsb3QgZm9yIGVhY2ggc2FtcGxlIHdpdGggYm90aCBwcmltZXIsIGJhc2VkIG9uIE9SREVSICMjIyMjIw0KDQojU0lMVkE6DQoNCiNGaW5kIHRvcCAyMCBvcmRlcnMgYW5kIHB1dCB0aGVtIGluIGEgdmVjdG9yICh1c2VkIHRvIGZpbHRlcikNCnRvcF9TSUxWQTQ1PC0gYXMuZGF0YS50YWJsZSh0YWJsZShTSUxWQTQ1X0Z1bGwkT3JkZXIpKSAjY291bnQgYnkgT3JkZXIuDQp0b3BfU0lMVkE0NTwtIHRvcF9TSUxWQTQ1W29yZGVyKHRvcF9TSUxWQTQ1JE4pXQ0KdG9wX1NJTFZBNDUgPC0gc2xpY2VfdGFpbCh0b3BfU0lMVkE0NSwgbj0yMCkNCnRvcF9TSUxWQTQ1IDwtIGFzLnZlY3Rvcih0YWlsKHRvcF9TSUxWQTQ1JFYxLDIwKSkNCnRvcF9TSUxWQTQ1ICNWZWN0b3IgY29udGFpbmluZyB0b3AgMjANCg0KdG9wX1NJTFZBNjg8LSBhcy5kYXRhLnRhYmxlKHRhYmxlKFNJTFZBNjhfRnVsbCRPcmRlcikpICNjb3VudCBieSBPcmRlci4NCnRvcF9TSUxWQTY4PC0gdG9wX1NJTFZBNjhbb3JkZXIodG9wX1NJTFZBNjgkTildDQp0b3BfU0lMVkE2OCA8LSBzbGljZV90YWlsKHRvcF9TSUxWQTY4LCBuPTIwKQ0KdG9wX1NJTFZBNjggPC0gYXMudmVjdG9yKHRhaWwodG9wX1NJTFZBNjgkVjEsMjApKQ0KdG9wX1NJTFZBNjggI1ZlY3RvciBjb250YWluaW5nIHRvcCAyMA0KDQp0b3BfR0c0NTwtIGFzLmRhdGEudGFibGUodGFibGUoR0c0NV9GdWxsJE9yZGVyKSkgI2NvdW50IGJ5IE9yZGVyLg0KdG9wX0dHNDU8LSB0b3BfR0c0NVtvcmRlcih0b3BfR0c0NSROKV0NCnRvcF9HRzQ1IDwtIHNsaWNlX3RhaWwodG9wX0dHNDUsIG49MjApDQp0b3BfR0c0NSA8LSBhcy52ZWN0b3IodGFpbCh0b3BfR0c0NSRWMSwyMCkpDQp0b3BfR0c0NSAjVmVjdG9yIGNvbnRhaW5pbmcgdG9wIDIwDQoNCnRvcF9HRzY4PC0gYXMuZGF0YS50YWJsZSh0YWJsZShHRzY4X0Z1bGwkT3JkZXIpKSAjY291bnQgYnkgT3JkZXIuDQp0b3BfR0c2ODwtIHRvcF9HRzY4W29yZGVyKHRvcF9HRzY4JE4pXQ0KdG9wX0dHNjggPC0gc2xpY2VfdGFpbCh0b3BfR0c2OCwgbj0yMCkNCnRvcF9HRzY4IDwtIGFzLnZlY3Rvcih0YWlsKHRvcF9HRzY4JFYxLDIwKSkNCnRvcF9HRzY4ICNWZWN0b3IgY29udGFpbmluZyB0b3AgMjANCg0KdG9wX1JEUDQ1PC0gYXMuZGF0YS50YWJsZSh0YWJsZShSRFA0NV9GdWxsJE9yZGVyKSkgI2NvdW50IGJ5IE9yZGVyLg0KdG9wX1JEUDQ1PC0gdG9wX1JEUDQ1W29yZGVyKHRvcF9SRFA0NSROKV0NCnRvcF9SRFA0NSA8LSBzbGljZV90YWlsKHRvcF9SRFA0NSwgbj0yMCkNCnRvcF9SRFA0NSA8LSBhcy52ZWN0b3IodGFpbCh0b3BfUkRQNDUkVjEsMjApKQ0KdG9wX1JEUDQ1ICNWZWN0b3IgY29udGFpbmluZyB0b3AgMjANCg0KdG9wX1JEUDY4PC0gYXMuZGF0YS50YWJsZSh0YWJsZShSRFA2OF9GdWxsJE9yZGVyKSkgI2NvdW50IGJ5IE9yZGVyLg0KdG9wX1JEUDY4PC0gdG9wX1JEUDY4W29yZGVyKHRvcF9SRFA2OCROKV0NCnRvcF9SRFA2OCA8LSBzbGljZV90YWlsKHRvcF9SRFA2OCwgbj0yMCkNCnRvcF9SRFA2OCA8LSBhcy52ZWN0b3IodGFpbCh0b3BfUkRQNjgkVjEsMjApKQ0KdG9wX1JEUDY4ICNWZWN0b3IgY29udGFpbmluZyB0b3AgMjANCg0KDQoNCiNGaWx0ZXIgcmVzdWx0cw0KdG9wMjBfU0lMVkE0NSA8LSBTSUxWQTQ1X0Z1bGwgJT4lIGZpbHRlcihPcmRlciA9PSB0b3BfU0lMVkE0NSkgI0ZpbHRlciBmb3Igb25seSB0aGUgb25lcyB3aXRoIHRoZSBuYW1lcyBvZiB0aGUgdG9wIDIwIG9yZGVycw0KdG9wMjBfU0lMVkE2OCA8LSBTSUxWQTY4X0Z1bGwgJT4lIGZpbHRlcihPcmRlciA9PSB0b3BfU0lMVkE2OCkgI0ZpbHRlciBmb3Igb25seSB0aGUgb25lcyB3aXRoIHRoZSBuYW1lcyBvZiB0aGUgdG9wIDIwIG9yZGVycw0KDQp0b3AyMF9HRzQ1IDwtIEdHNDVfRnVsbCAlPiUgZmlsdGVyKE9yZGVyID09IHRvcF9HRzQ1KSAjRmlsdGVyIGZvciBvbmx5IHRoZSBvbmVzIHdpdGggdGhlIG5hbWVzIG9mIHRoZSB0b3AgMjAgb3JkZXJzDQp0b3AyMF9HRzY4IDwtIEdHNjhfRnVsbCAlPiUgZmlsdGVyKE9yZGVyID09IHRvcF9HRzY4KSAjRmlsdGVyIGZvciBvbmx5IHRoZSBvbmVzIHdpdGggdGhlIG5hbWVzIG9mIHRoZSB0b3AgMjAgb3JkZXJzDQoNCnRvcDIwX1JEUDQ1IDwtIFJEUDQ1X0Z1bGwgJT4lIGZpbHRlcihPcmRlciA9PSB0b3BfUkRQNDUpICNGaWx0ZXIgZm9yIG9ubHkgdGhlIG9uZXMgd2l0aCB0aGUgbmFtZXMgb2YgdGhlIHRvcCAyMCBvcmRlcnMNCnRvcDIwX1JEUDY4IDwtIFJEUDY4X0Z1bGwgJT4lIGZpbHRlcihPcmRlciA9PSB0b3BfUkRQNjgpICNGaWx0ZXIgZm9yIG9ubHkgdGhlIG9uZXMgd2l0aCB0aGUgbmFtZXMgb2YgdGhlIHRvcCAyMCBvcmRlcnMNCg0KDQoNCg0KR0c0NSA8LSBnZ3Bsb3QodG9wMjBfR0c0NSwgYWVzKHggPSBTQU1QTEVfTkFNRSwgeSA9IENvdW50cywgZmlsbCA9IE9yZGVyKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIiwgc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2dwbG90KHRvcDIwX0dHNDUsIGFlcyhmaWxsPUNvdW50cywgeT0xLCB4PTEpKSArIA0KICAgIHRoZW1lKGF4aXMudGV4dC54PSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplPTcpKSArZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJPcmRlciIpKSt5bGFiKGxhYmVsPSJSZWxhdGl2ZSBhYnVuZGFuY2UiKSsNCiAgICBnZ3RpdGxlKCJUb3AgMjAgT3JkZXJzIGZyb20gR3JlZW5HZW5lcyBpbiBzYW1wbGVzIHNlcXVlbmNlZCBieSBWNC1WNSByZWdpb24iKSsgIyBmb3IgdGhlIG1haW4gdGl0bGUNCiAgICBnZW9tX2Jhcihwb3NpdGlvbj0iZmlsbCIsIHN0YXQ9ImlkZW50aXR5IikgKyBleHBhbmRfbGltaXRzKHkgPSA5LCB4PS05KSAjIG9yIHNvbWUgb3RoZXIgYXJiaXRyYXJpbHkgbGFyZ2UgbnVtYmVyDQpHRzQ1DQoNCg0KR0c2OCA8LSBnZ3Bsb3QodG9wMjBfR0c2OCwgYWVzKHggPSBDb3VudHMsIHkgPSBTYW1wbGUsIGZpbGwgPSBPcmRlcikpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIsIHN0YXQgPSAiaWRlbnRpdHkiKQ0KICAgIGdncGxvdCh0b3AyMF9HRzY4LCBhZXMoZmlsbD1Db3VudHMsIHk9MSwgeD0xKSkgKyANCiAgICBnZ3RpdGxlKCJUb3AgMjAgT3JkZXJzIGZyb20gR3JlZW5HZW5lcyBpbiBzYW1wbGVzIHNlcXVlbmNlZCBieSBWNi1WOCByZWdpb24iKSsgIyBmb3IgdGhlIG1haW4gdGl0bGUNCiAgICBnZW9tX2Jhcihwb3NpdGlvbj0iZmlsbCIsIHN0YXQ9ImlkZW50aXR5IikgKyBleHBhbmRfbGltaXRzKHkgPSA5LCB4PS05KSAgIyBvciBzb21lIG90aGVyIGFyYml0cmFyaWx5IGxhcmdlIG51bWJlcg0KR0c2OA0KDQoNCg0KUzQ1IDwtIGdncGxvdCh0b3AyMF9TSUxWQTQ1LCBhZXMoeCA9IENvdW50cywgeSA9IFNhbXBsZSwgZmlsbCA9IE9yZGVyKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIiwgc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2dwbG90KHRvcDIwX1NJTFZBNDUsIGFlcyhmaWxsPUNvdW50cywgeT0xLCB4PTEpKSArIA0KICAgIGdndGl0bGUoIlRvcCAyMCBPcmRlcnMgZnJvbSBTSUxWQSBpbiBzYW1wbGVzIHNlcXVlbmNlZCBieSBWNC1WNSByZWdpb24iKSsgIyBmb3IgdGhlIG1haW4gdGl0bGUNCiAgICBnZW9tX2Jhcihwb3NpdGlvbj0iZmlsbCIsIHN0YXQ9ImlkZW50aXR5IikgKyBleHBhbmRfbGltaXRzKHkgPSA5LCB4PS05KSAgIyBvciBzb21lIG90aGVyIGFyYml0cmFyaWx5IGxhcmdlIG51bWJlcg0KUzQ1DQoNCg0KUzY4IDwtIGdncGxvdCh0b3AyMF9TSUxWQTY4LCBhZXMoeCA9IENvdW50cywgeSA9IFNhbXBsZSwgZmlsbCA9IE9yZGVyKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIiwgc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2dwbG90KHRvcDIwX1NJTFZBNjgsIGFlcyhmaWxsPUNvdW50cywgeT0xLCB4PTEpKSArIA0KICAgIGdndGl0bGUoIlRvcCAyMCBPcmRlcnMgZnJvbSBTSUxWQSBpbiBzYW1wbGVzIHNlcXVlbmNlZCBieSBWNi1WOCByZWdpb24iKSsgIyBmb3IgdGhlIG1haW4gdGl0bGUNCiAgICBnZW9tX2Jhcihwb3NpdGlvbj0iZmlsbCIsIHN0YXQ9ImlkZW50aXR5IikgKyBleHBhbmRfbGltaXRzKHkgPSA5LCB4PS05KSAgIyBvciBzb21lIG90aGVyIGFyYml0cmFyaWx5IGxhcmdlIG51bWJlcg0KUzY4DQoNCg0KUkRQNDUgPC0gZ2dwbG90KHRvcDIwX1JEUDQ1LCBhZXMoeCA9IENvdW50cywgeSA9IFNhbXBsZSwgZmlsbCA9IE9yZGVyKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIiwgc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2dwbG90KHRvcDIwX1JEUDQ1LCBhZXMoZmlsbD1Db3VudHMsIHk9MSwgeD0xKSkgKyANCiAgICBnZ3RpdGxlKCJUb3AgMjAgT3JkZXJzIGZyb20gR3JlZW5HZW5lcyBpbiBzYW1wbGVzIHNlcXVlbmNlZCBieSBWNi1WOCByZWdpb24iKSsgIyBmb3IgdGhlIG1haW4gdGl0bGUNCiAgICBnZW9tX2Jhcihwb3NpdGlvbj0iZmlsbCIsIHN0YXQ9ImlkZW50aXR5IikgKyBleHBhbmRfbGltaXRzKHkgPSA5LCB4PS05KSAgIyBvciBzb21lIG90aGVyIGFyYml0cmFyaWx5IGxhcmdlIG51bWJlcg0KUkRQNDUNCg0KI1dvcmtpbmcgb24gYXNzaWduaW5nIHNwZWNpZmljIGNvbG91cnMuLi4NCg0KY29sb3VyQXNzaWduID0gYygiRnJhbmtpYWxlcyI9ImJsdWUiLCJNaWNyb3RyaWNoYWxlcyI9ImNvcmFsMyIsIk1hcmluZSBHcm91cCBJSSI9ImNoYXJ0cmV1c2U0IiwiVmVycnVjb21pY3JvYmlhbGVzIj0iZGVlcHBpbmszIiwiT2NlYW5vc3BpcmlsbGFsZXMiPSJkYXJrdmlvbGV0IiwiU3BoaW5nb2JhY3RlcmlhbGVzIj0ibWFyb29uMyIsIkFsdGVyb21vbmFkYWxlcyI9InBhbGV0dXJxdW9pc2U0IiwiUmlja2V0dHNpYWxlcyI9InNlYWdyZWVuNCIsIkNlbGx2aWJyaW9uYWxlcyI9Im9yYW5nZXJlZDIiLCJQaXJlbGx1bGFsZXMiPSJvcmFuZ2UzIiwiTml0cm9zb3B1bWlsYWxlcyI9InJveWFsYmx1ZTMiLCJTcGhpbmdvbW9uYWRhbGVzIj0icmFzcGJicmF3bjMiLCJTQVIxMSBjbGFkZSI9Im5hdnlibHVlIiwiQ3l0b3BoYWdhbGVzIj0iYnJvd24zIiwiUmhvZG9iYWN0ZXJhbGVzIj0iZGFya2N5YW4iLCJDaGl0aW5vcGhhZ2FsZXMiPSJmaXJlYnJpY2szIiwiICI9ImdyYXk0NiIsIkNobG9yb3BsYXN0Ij0ibWVkaXVtc2VhZ3JlZW4iLCJCZXRhcHJvdGVvYmFjdGVyaWFsZXMiPSJtZWRpdW1wdXJwbGUyIiwiRmxhdm9iYWN0ZXJpYWxlcyI9ImdvbGRlbnJvZDEiKQ0KDQojY29sb3VyQXNzaWduID0gYygiYmx1ZSIsImNvcmFsMyIsImNoYXJ0cmV1c2U0IiwiZGVlcHBpbmszIiwiZGFya3Zpb2xldCIsIm1hcm9vbjMiLCJwYWxldHVycXVvaXNlNCIsInNlYWdyZWVuNCIsIm9yYW5nZXJlZDIiLCJvcmFuZ2UzIiwicm95YWxibHVlMyIsInJhc3BiYnJhd24zIiwibmF2eWJsdWUiLCJicm93bjMiLCJkYXJrY3lhbiIsImZpcmVicmljazMiLCJncmF5NDYiLCJtZWRpdW1zZWFncmVlbiIsIm1lZGl1bXB1cnBsZTIiLCJnb2xkZW5yb2QxIikNCg0KDQpSRFA2OCA8LSBnZ3Bsb3QodG9wMjBfUkRQNjgsIGFlcyh4ID0gQ291bnRzLCB5ID0gU2FtcGxlLCBmaWxsID0gT3JkZXIpKSArIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCBzdGF0ID0gImlkZW50aXR5IikNCiAgICBnZ3Bsb3QodG9wMjBfUkRQNjgsIGFlcyhmaWxsPUNvdW50cywgeT0xLCB4PTEpKSArIA0KICAgIGdndGl0bGUoIlRvcCAyMCBPcmRlcnMgZnJvbSBHcmVlbkdlbmVzIGluIHNhbXBsZXMgc2VxdWVuY2VkIGJ5IFY2LVY4IHJlZ2lvbiIpKyAjIGZvciB0aGUgbWFpbiB0aXRsZQ0KICAgIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIGV4cGFuZF9saW1pdHMoeSA9IDksIHg9LTkpKyAgIyBvciBzb21lIG90aGVyIGFyYml0cmFyaWx5IGxhcmdlIG51bWJlcg0KICAgICNzY2FsZV9maWxsX21hbnVhbCgibGVnZW5kIiwgdmFsdWVzID0gY29sb3VyQXNzaWduKQ0KICAgICN0aGVtZV9idygpK3NjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jb2xvdXJBc3NpZ24pDQogICAgICAgIA0KUkRQNjgNCg0KDQo/IHNjYWxlX2ZpbGxfbWFudWFsDQoNCiNhc3NpZ24gY29sb3VyLCBlYWNoIGxpbmUgaXMgZm9yIHNwZWNpZmljIHBoeWxhIChtb3JlIGNvbG91cj0gZm9yIG1vcmUgcGh5bGEsIHdoZXJlIHkgKGFzc2lnbmF0aW9uKT0gbXkgdGF4b25vbXkpOg0KY29sPWMoImJsdWUiLCAiY2hhcnRyZXVzZTQiLCAiZGFya2dyZWVuIiwgInllbGxvdyIsICJnb2xkZW5yb2Q0IiwgImNoYXJ0cmV1c2UyIiwgImRhcmtvbGl2ZWdyZWVuIiwgImNvcm5zaWxrIiwgImNvcm5zaWxrNCIpDQpjb2w9YygiYmx1ZSIsICJjaGFydHJldXNlNCIsICJkYXJrZ3JlZW4iLCAieWVsbG93IiwiZ29sZGVucm9kIiwgImRhcmtnb2xkZW5yb2QyIikNCmNvbD1jKCJibGFjayIsICJwdXJwbGUiKQ0KbG9uZ190cm9waHMyICU+JQ0KICBnZ3Bsb3QoYWVzKHg9RGVwdGgsIHk9YXNzaWduYXRpb24sIHNpemUgPSByZWxfYWJ1bmQsIGZpbGw9U3RhZ2UpKSArDQogIGdlb21fcG9pbnQoIGNvbG91cj0iYmxhY2siLCBwY2g9MjEpICsgZmFjZXRfZ3JpZCguIH4gU3RhZ2UsIGRyb3A9VFJVRSxzY2FsZT0iZnJlZSIsc3BhY2U9ImZyZWVfeCIpKw0KICB0aGVtZV9idygpK3NjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jb2wpKw0KICB0aGVtZShheGlzLnRleHQueD0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZT04KSkrDQogIHRoZW1lKGF4aXMudGV4dC55PSBlbGVtZW50X3RleHQoc2l6ZT04KSkNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCmBgYHtyfQ0KI1RvcCAyMCBwaHlsdW0gb2YgZWFjaCBkYXRhYmFzZSBhbmQgZWFjaCBwcmltZXIgYXMgdGFibGVzDQoNCg0KI1NJTFZBOg0KDQojU29ydCBvdXQgdGhlIGNvdW50cyBvZiBPcmRlcnMNCnBoeWx1bUNvdW50NDVfU0lMVkE8LSBhcy5kYXRhLnRhYmxlKHRhYmxlKFNJTFZBNDVfRnVsbCRQaHlsdW0pKSAjY291bnQgYnkgUGh5bHVtLg0KcGh5bHVtQ291bnQ0NV9TSUxWQTwtIHBoeWx1bUNvdW50NDVfU0lMVkFbb3JkZXIocGh5bHVtQ291bnQ0NV9TSUxWQSROKV0NCnBoeWx1bUNvdW50NDVfU0lMVkEgI1YxIGlzIHRoZSBQaHlsdW0gbmFtZSwgTiBpcyB0aGUgY291bnQuDQoNCnBoeWx1bUNvdW50NjhfU0lMVkE8LSBhcy5kYXRhLnRhYmxlKHRhYmxlKFNJTFZBNjhfRnVsbCRQaHlsdW0pKSAjY291bnQgYnkgUGh5bHVtLg0KcGh5bHVtQ291bnQ2OF9TSUxWQTwtIHBoeWx1bUNvdW50NjhfU0lMVkFbb3JkZXIocGh5bHVtQ291bnQ2OF9TSUxWQSROKV0NCnBoeWx1bUNvdW50NjhfU0lMVkEgI1YxIGlzIHRoZSBQaHlsdW0gbmFtZSwgTiBpcyB0aGUgY291bnQuDQoNCiNHZXQgdG9wIE9yZGVycw0KdG9wVGF4YTQ1X1NJTFZBX1BoeSA8LSBzbGljZV90YWlsKHBoeWx1bUNvdW50NDVfU0lMVkEsIG49MjApICNnZXQgdGhlIGJvdHRvbSAyMCBjb3VudHMgKGl0J3MgYnkgYXNjZW5kaW5nIG9yZGVyKQ0KdG9wVGF4YTQ1X1NJTFZBX1BoeQ0KDQp0b3BUYXhhNjhfU0lMVkFfUGh5IDwtIHNsaWNlX3RhaWwocGh5bHVtQ291bnQ2OF9TSUxWQSxuPTIwKQ0KdG9wVGF4YTY4X1NJTFZBX1BoeQ0KDQoNCiNHcmVlbiBHZW5lczoNCg0KI1NvcnQgb3V0IHRoZSBjb3VudHMgb2YgT3JkZXJzDQpwaHlsdW1Db3VudDQ1X0dHPC0gYXMuZGF0YS50YWJsZSh0YWJsZShHRzQ1X0Z1bGwkUGh5bHVtKSkgI2NvdW50IGJ5IFBoeWx1bS4NCnBoeWx1bUNvdW50NDVfR0c8LSBwaHlsdW1Db3VudDQ1X0dHW29yZGVyKHBoeWx1bUNvdW50NDVfR0ckTildDQpwaHlsdW1Db3VudDQ1X0dHICNWMSBpcyB0aGUgUGh5bHVtIG5hbWUsIE4gaXMgdGhlIGNvdW50Lg0KDQpwaHlsdW1Db3VudDY4X0dHPC0gYXMuZGF0YS50YWJsZSh0YWJsZShHRzY4X0Z1bGwkUGh5bHVtKSkgI2NvdW50IGJ5IFBoeWx1bS4NCnBoeWx1bUNvdW50NjhfR0c8LSBwaHlsdW1Db3VudDY4X0dHW29yZGVyKHBoeWx1bUNvdW50NjhfR0ckTildDQpwaHlsdW1Db3VudDY4X0dHICNWMSBpcyB0aGUgUGh5bHVtIG5hbWUsIE4gaXMgdGhlIGNvdW50Lg0KDQojR2V0IHRvcCBPcmRlcnMNCnRvcFRheGE0NV9HR19QaHkgPC0gc2xpY2VfdGFpbChwaHlsdW1Db3VudDQ1X0dHLCBuPTIwKSAjZ2V0IHRoZSBib3R0b20gMjAgY291bnRzIChpdCdzIGJ5IGFzY2VuZGluZyBvcmRlcikNCnRvcFRheGE0NV9HR19QaHkNCg0KdG9wVGF4YTY4X0dHX1BoeSA8LSBzbGljZV90YWlsKHBoeWx1bUNvdW50NjhfR0csbj0yMCkNCnRvcFRheGE2OF9HR19QaHkNCg0KDQojUkRQOg0KDQojU29ydCBvdXQgdGhlIGNvdW50cyBvZiBPcmRlcnMNCnBoeWx1bUNvdW50NDVfUkRQPC0gYXMuZGF0YS50YWJsZSh0YWJsZShSRFA0NV9GdWxsJFBoeWx1bSkpICNjb3VudCBieSBQaHlsdW0uDQpwaHlsdW1Db3VudDQ1X1JEUDwtIHBoeWx1bUNvdW50NDVfUkRQW29yZGVyKHBoeWx1bUNvdW50NDVfUkRQJE4pXQ0KcGh5bHVtQ291bnQ0NV9SRFAgI1YxIGlzIHRoZSBQaHlsdW0gbmFtZSwgTiBpcyB0aGUgY291bnQuDQoNCnBoeWx1bUNvdW50NjhfUkRQPC0gYXMuZGF0YS50YWJsZSh0YWJsZShSRFA2OF9GdWxsJFBoeWx1bSkpICNjb3VudCBieSBQaHlsdW0uDQpwaHlsdW1Db3VudDY4X1JEUDwtIHBoeWx1bUNvdW50NjhfUkRQW29yZGVyKHBoeWx1bUNvdW50NjhfUkRQJE4pXQ0KcGh5bHVtQ291bnQ2OF9SRFAgI1YxIGlzIHRoZSBQaHlsdW0gbmFtZSwgTiBpcyB0aGUgY291bnQuDQoNCiNHZXQgdG9wIE9yZGVycw0KdG9wVGF4YTQ1X1JEUF9QaHkgPC0gc2xpY2VfdGFpbChwaHlsdW1Db3VudDQ1X1JEUCwgbj0yMCkgI2dldCB0aGUgYm90dG9tIDIwIGNvdW50cyAoaXQncyBieSBhc2NlbmRpbmcgb3JkZXIpDQp0b3BUYXhhNDVfUkRQX1BoeQ0KDQp0b3BUYXhhNjhfR0dfUGh5IDwtIHNsaWNlX3RhaWwocGh5bHVtQ291bnQ2OF9SRFAsbj0yMCkNCnRvcFRheGE2OF9HR19QaHkNCmBgYA0KDQpgYGB7cn0NCiMjIyMjUHJvcG9ydGlvbiBwbG90IGZvciBlYWNoIHNhbXBsZSB3aXRoIGJvdGggcHJpbWVyLCBiYXNlZCBvbiBQSFlMVU0gIyMjIyMjDQoNCiNTSUxWQToNCg0KI0ZpbmQgdG9wIDIwIG9yZGVycyBhbmQgcHV0IHRoZW0gaW4gYSB2ZWN0b3IgKHVzZWQgdG8gZmlsdGVyKQ0KdG9wX1NJTFZBNDVfUGh5PC0gYXMuZGF0YS50YWJsZSh0YWJsZShTSUxWQTQ1X0Z1bGwkUGh5bHVtKSkgI2NvdW50IGJ5IFBoeWx1bS4NCnRvcF9TSUxWQTQ1X1BoeTwtIHRvcF9TSUxWQTQ1X1BoeVtvcmRlcih0b3BfU0lMVkE0NV9QaHkkTildDQp0b3BfU0lMVkE0NV9QaHkgPC0gc2xpY2VfdGFpbCh0b3BfU0lMVkE0NV9QaHksIG49MjApDQp0b3BfU0lMVkE0NV9QaHkgPC0gYXMudmVjdG9yKHRhaWwodG9wX1NJTFZBNDVfUGh5JFYxLDIwKSkNCnRvcF9TSUxWQTQ1X1BoeSAjVmVjdG9yIGNvbnRhaW5pbmcgdG9wIDIwDQoNCnRvcF9TSUxWQTY4X1BoeTwtIGFzLmRhdGEudGFibGUodGFibGUoU0lMVkE2OF9GdWxsJFBoeWx1bSkpICNjb3VudCBieSBQaHlsdW0uDQp0b3BfU0lMVkE2OF9QaHk8LSB0b3BfU0lMVkE2OF9QaHlbb3JkZXIodG9wX1NJTFZBNjhfUGh5JE4pXQ0KdG9wX1NJTFZBNjhfUGh5IDwtIHNsaWNlX3RhaWwodG9wX1NJTFZBNjhfUGh5LCBuPTIwKQ0KdG9wX1NJTFZBNjhfUGh5IDwtIGFzLnZlY3Rvcih0YWlsKHRvcF9TSUxWQTY4X1BoeSRWMSwyMCkpDQp0b3BfU0lMVkE2OF9QaHkgI1ZlY3RvciBjb250YWluaW5nIHRvcCAyMA0KDQp0b3BfR0c0NV9QaHk8LSBhcy5kYXRhLnRhYmxlKHRhYmxlKEdHNDVfRnVsbCRQaHlsdW0pKSAjY291bnQgYnkgUGh5bHVtLg0KdG9wX0dHNDVfUGh5PC0gdG9wX0dHNDVfUGh5W29yZGVyKHRvcF9HRzQ1X1BoeSROKV0NCnRvcF9HRzQ1X1BoeSA8LSBzbGljZV90YWlsKHRvcF9HRzQ1X1BoeSwgbj0yMCkNCnRvcF9HRzQ1X1BoeSAjVmVjdG9yIGNvbnRhaW5pbmcgdG9wIDIwDQoNCnRvcF9HRzY4X1BoeTwtIGFzLmRhdGEudGFibGUodGFibGUoR0c2OF9GdWxsJFBoeWx1bSkpICNjb3VudCBieSBQaHlsdW0uDQp0b3BfR0c2OF9QaHk8LSB0b3BfR0c2OF9QaHlbb3JkZXIodG9wX0dHNjhfUGh5JE4pXQ0KdG9wX0dHNjhfUGh5IDwtIHNsaWNlX3RhaWwodG9wX0dHNjhfUGh5LCBuPTIwKQ0KdG9wX0dHNjhfUGh5IDwtIGFzLnZlY3Rvcih0YWlsKHRvcF9HRzY4X1BoeSRWMSwyMCkpDQp0b3BfR0c2OF9QaHkgI1ZlY3RvciBjb250YWluaW5nIHRvcCAyMA0KDQp0b3BfUkRQNDVfUGh5PC0gYXMuZGF0YS50YWJsZSh0YWJsZShSRFA0NV9GdWxsJFBoeWx1bSkpICNjb3VudCBieSBQaHlsdW0uDQp0b3BfUkRQNDVfUGh5PC0gdG9wX1JEUDQ1X1BoeVtvcmRlcih0b3BfUkRQNDVfUGh5JE4pXQ0KdG9wX1JEUDQ1X1BoeSA8LSBzbGljZV90YWlsKHRvcF9SRFA0NV9QaHksIG49MjApDQp0b3BfUkRQNDVfUGh5IDwtIGFzLnZlY3Rvcih0YWlsKHRvcF9SRFA0NV9QaHkkVjEsMjApKQ0KdG9wX1JEUDQ1X1BoeSAjVmVjdG9yIGNvbnRhaW5pbmcgdG9wIDIwDQoNCnRvcF9SRFA2OF9QaHk8LSBhcy5kYXRhLnRhYmxlKHRhYmxlKFJEUDY4X0Z1bGwkUGh5bHVtKSkgI2NvdW50IGJ5IFBoeWx1bS4NCnRvcF9SRFA2OF9QaHk8LSB0b3BfUkRQNjhfUGh5W29yZGVyKHRvcF9SRFA2OF9QaHkkTildDQp0b3BfUkRQNjhfUGh5IDwtIHNsaWNlX3RhaWwodG9wX1JEUDY4X1BoeSwgbj0yMCkNCnRvcF9SRFA2OF9QaHkgPC0gYXMudmVjdG9yKHRhaWwodG9wX1JEUDY4X1BoeSRWMSwyMCkpDQp0b3BfUkRQNjhfUGh5ICNWZWN0b3IgY29udGFpbmluZyB0b3AgMjANCg0KI0NhbGN1bGF0ZSBwcm9wb3J0aW9uDQojIFBfU0lMXzQ1PC10b3BfU0lMVkE0NV9QaHlbLC0xXQ0KIyB0b3R1PC10KFBfU0lMXzQ1KQ0KIyB4PC10b3R1L3Jvd1N1bXModG90dSkNCiMgeDwtbmEub21pdCh4KQ0KIyBwcm9wUGh5X1NJTF80NTwtdCh4KQ0KIyBwcm9wUGh5X1NJTF80NSA8LSBhcy5kYXRhLmZyYW1lKHByb3BQaHlfU0lMXzQ1KQ0KIyBwcm9wUGh5X1NJTF80NSRQaHlsYSA8LSB0b3BfU0lMVkE0NV9QaHkNCg0KI0ZpbHRlciByZXN1bHRzDQp0b3AyMF9TSUxWQTQ1X1BoeSA8LSBTSUxWQTQ1X0Z1bGwgJT4lIGZpbHRlcihQaHlsdW0gPT0gdG9wX1NJTFZBNDVfUGh5KSAjRmlsdGVyIGZvciBvbmx5IHRoZSBvbmVzIHdpdGggdGhlIG5hbWVzIG9mIHRoZSB0b3AgMjAgb3JkZXJzDQp0b3AyMF9TSUxWQTY4X1BoeSA8LSBTSUxWQTY4X0Z1bGwgJT4lIGZpbHRlcihQaHlsdW0gPT0gdG9wX1NJTFZBNjhfUGh5KSAjRmlsdGVyIGZvciBvbmx5IHRoZSBvbmVzIHdpdGggdGhlIG5hbWVzIG9mIHRoZSB0b3AgMjAgb3JkZXJzDQoNCnRvcDIwX0dHNDVfUGh5IDwtIEdHNDVfRnVsbCAlPiUgZmlsdGVyKFBoeWx1bSA9PSB0b3BfR0c0NV9QaHkpICNGaWx0ZXIgZm9yIG9ubHkgdGhlIG9uZXMgd2l0aCB0aGUgbmFtZXMgb2YgdGhlIHRvcCAyMCBvcmRlcnMNCnRvcDIwX0dHNjhfUGh5IDwtIEdHNjhfRnVsbCAlPiUgZmlsdGVyKFBoeWx1bSA9PSB0b3BfR0c2OF9QaHkpICNGaWx0ZXIgZm9yIG9ubHkgdGhlIG9uZXMgd2l0aCB0aGUgbmFtZXMgb2YgdGhlIHRvcCAyMCBvcmRlcnMNCg0KdG9wMjBfUkRQNDVfUGh5IDwtIFJEUDQ1X0Z1bGwgJT4lIGZpbHRlcihQaHlsdW0gPT0gdG9wX1JEUDQ1X1BoeSkgI0ZpbHRlciBmb3Igb25seSB0aGUgb25lcyB3aXRoIHRoZSBuYW1lcyBvZiB0aGUgdG9wIDIwIG9yZGVycw0KdG9wMjBfUkRQNjhfUGh5IDwtIFJEUDY4X0Z1bGwgJT4lIGZpbHRlcihQaHlsdW0gPT0gdG9wX1JEUDY4X1BoeSkgI0ZpbHRlciBmb3Igb25seSB0aGUgb25lcyB3aXRoIHRoZSBuYW1lcyBvZiB0aGUgdG9wIDIwIG9yZGVycw0KDQoNCg0KY29sb3VyQXNzaWduID0gYygiTGVudGlzcGhhZXJhZSI9ImRhcmt2aW9sZXQiLCJOaXRyb3NwaXJhZSI9Im1hcm9vbjMiLCJOYW5vYXJjaGFlYWVvdGEiPSJwYWxldHVycXVvaXNlNCIsIkFybWF0aW1vbmFkZXRlcyI9InNlYWdyZWVuNCIsIkdlbW1hdGltb25hZGV0ZXMiPSJvcmFuZ2VyZWQyIiwgIkNobG9yb2ZsZXhpIj0ib3JhbmdlMyIsIk5pdHJvc3BpbmFlIj0icm95YWxibHVlMyIsIlBhdGVzY2liYWN0ZXJpYSI9InZpb2xldHJlZCIsIk1hcmluaW1pY3JvYmlhIChTQVI0MDYgY2xhZGUpIj0iZGVlcHNreWJsdWUxIiwiRmlybWljdXRlcyI9ImJyb3duMyIsICJFdXJ5YXJjaGFlb3RhIj0iZGFya2N5YW4iLCJBY2lkb2JhY3RlcmlhIj0iZmlyZWJyaWNrMyIsIlZlcnJ1Y29taWNyb2JpYSI9ImdyYXk0NiIsICJUaGF1bWFyY2hhZW90YSI9Im1lZGl1bXNlYWdyZWVuIiwgIiAiPSJtZWRpdW1wdXJwbGUyIiwgIkFjdGlub2JhY3RlcmlhIj0iZ29sZGVucm9kMSIsICJQbGFuY3RvbXljZXRlcyI9Im9yY2hpZDQiLCAiQ3lhbm9iYWN0ZXJpYSI9ImRhcmtzbGF0ZWdyZXkiLCAiQmFjdGVyb2lkZXRlcyI9Im1lZGl1bXB1cnBsZTEiLCJQcm90ZW9iYWN0ZXJpYSI9InNhbG1vbjEiKQ0KDQoNClM0NSA8LSBnZ3Bsb3QodG9wMjBfU0lMVkE0NV9QaHksYWVzKHg9aS5TQU1QTEVfTkFNRSwgeT1Db3VudHMsIGZpbGw9UGh5bHVtKSkgKw0KZ2d0aXRsZSgiVG9wIDIwIFBoeWxhIGZyb20gU0lMVkEgaW4gc2FtcGxlcyBzZXF1ZW5jZWQgYnkgVjQtVjUgcmVnaW9uIikrICMgZm9yIHRoZSBtYWluIHRpdGxlDQpnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uPSJmaWxsIikrIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jb2xvdXJBc3NpZ24pK3RoZW1lX2J3KCkrDQp0aGVtZShheGlzLnRleHQueD0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZT03KSkgK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT0iT3JkZXIiKSkreWxhYihsYWJlbD0iUmVsYXRpdmUgYWJ1bmRhbmNlIikNCg0KUzQ1DQoNClM2OCA8LSBnZ3Bsb3QodG9wMjBfU0lMVkE2OF9QaHksYWVzKHg9aS5TQU1QTEVfTkFNRSwgeT1Db3VudHMsIGZpbGw9UGh5bHVtKSkgKw0KZ2d0aXRsZSgiVG9wIDIwIE9yZGVycyBmcm9tIFNJTFZBIGluIHNhbXBsZXMgc2VxdWVuY2VkIGJ5IFY2LVY4IHJlZ2lvbiIpKyAjIGZvciB0aGUgbWFpbiB0aXRsZQ0KZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbj0iZmlsbCIpKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sb3VyQXNzaWduX3BoeSkrdGhlbWVfYncoKSsNCnRoZW1lKGF4aXMudGV4dC54PSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplPTcpKSArZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJPcmRlciIpKSt5bGFiKGxhYmVsPSJSZWxhdGl2ZSBhYnVuZGFuY2UiKQ0KDQpTNjgNCg0KI09sZCBtZXRob2QNCiMgDQojIFM0NSA8LSBnZ3Bsb3QodG9wMjBfU0lMVkE0NV9QaHksIGFlcyh4ID0gaS5TQU1QTEVfTkFNRSwgeSA9IENvdW50cywgZmlsbCA9IFBoeWx1bSkpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIsIHN0YXQgPSAiaWRlbnRpdHkiKQ0KIyAgICAgZ2dwbG90KHRvcDIwX1NJTFZBNDVfUGh5LCBhZXMoZmlsbD1Db3VudHMsIHk9MSwgeD0xKSkgKyANCiMgICAgIGdndGl0bGUoIlRvcCAyMCBQaHlsYSBmcm9tIFNJTFZBIGluIHNhbXBsZXMgc2VxdWVuY2VkIGJ5IFY0LVY1IHJlZ2lvbiIpKyAjIGZvciB0aGUgbWFpbiB0aXRsZQ0KIyAgICAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgZXhwYW5kX2xpbWl0cyh5ID0gOSwgeD0tOSkgICMgb3Igc29tZSBvdGhlciBhcmJpdHJhcmlseSBsYXJnZSBudW1iZXINCiMgUzQ1DQojIA0KIyANCiMgUzY4IDwtIGdncGxvdCh0b3AyMF9TSUxWQTY4X1BoeSwgYWVzKHggPSBDb3VudHMsIHkgPSBpLlNBTVBMRV9OQU1FLCBmaWxsID0gUGh5bHVtKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIiwgc3RhdCA9ICJpZGVudGl0eSIpDQojICAgICBnZ3Bsb3QodG9wMjBfU0lMVkE2OF9QaHksIGFlcyhmaWxsPUNvdW50cywgeT0xLCB4PTEpKSArIA0KIyAgICAgZ2d0aXRsZSgiVG9wIDIwIE9yZGVycyBmcm9tIFNJTFZBIGluIHNhbXBsZXMgc2VxdWVuY2VkIGJ5IFY2LVY4IHJlZ2lvbiIpKyAjIGZvciB0aGUgbWFpbiB0aXRsZQ0KIyAgICAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgZXhwYW5kX2xpbWl0cyh5ID0gOSwgeD0tOSkgICMgb3Igc29tZSBvdGhlciBhcmJpdHJhcmlseSBsYXJnZSBudW1iZXINCiMgUzY4DQojIA0KIyANCiMgR0c0NSA8LSBnZ3Bsb3QodG9wMjBfR0c0NV9QaHksIGFlcyh4ID0gQ291bnRzLCB5ID0gaS5TQU1QTEVfTkFNRSwgZmlsbCA9IFBoeWx1bSkpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIsIHN0YXQgPSAiaWRlbnRpdHkiKQ0KIyAgICAgZ2dwbG90KHRvcDIwX0dHNDVfUGh5LCBhZXMoZmlsbD1Db3VudHMsIHk9MSwgeD0xKSkgKyANCiMgICAgIGdndGl0bGUoIlRvcCAyMCBPcmRlcnMgZnJvbSBHcmVlbkdlbmVzIGluIHNhbXBsZXMgc2VxdWVuY2VkIGJ5IFY0LVY1IHJlZ2lvbiIpKyAjIGZvciB0aGUgbWFpbiB0aXRsZQ0KIyAgICAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgZXhwYW5kX2xpbWl0cyh5ID0gOSwgeD0tOSkgICMgb3Igc29tZSBvdGhlciBhcmJpdHJhcmlseSBsYXJnZSBudW1iZXINCiMgR0c0NQ0KIyANCiMgDQojIEdHNjggPC0gZ2dwbG90KHRvcDIwX0dHNjhfUGh5LCBhZXMoeCA9IENvdW50cywgeSA9IGkuU0FNUExFX05BTUUsIGZpbGwgPSBQaHlsdW0pKSArIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCBzdGF0ID0gImlkZW50aXR5IikNCiMgICAgIGdncGxvdCh0b3AyMF9HRzY4X1BoeSwgYWVzKGZpbGw9Q291bnRzLCB5PTEsIHg9MSkpICsgDQojICAgICBnZ3RpdGxlKCJUb3AgMjAgT3JkZXJzIGZyb20gR3JlZW5HZW5lcyBpbiBzYW1wbGVzIHNlcXVlbmNlZCBieSBWNi1WOCByZWdpb24iKSsgIyBmb3IgdGhlIG1haW4gdGl0bGUNCiMgICAgIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIGV4cGFuZF9saW1pdHMoeSA9IDksIHg9LTkpICAjIG9yIHNvbWUgb3RoZXIgYXJiaXRyYXJpbHkgbGFyZ2UgbnVtYmVyDQojIEdHNjgNCiMgDQojIA0KIyBSRFA0NSA8LSBnZ3Bsb3QodG9wMjBfUkRQNDVfUGh5LCBhZXMoeCA9IENvdW50cywgeSA9IGkuU0FNUExFX05BTUUsIGZpbGwgPSBQaHlsdW0pKSArIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCBzdGF0ID0gImlkZW50aXR5IikNCiMgICAgIGdncGxvdCh0b3AyMF9SRFA0NV9QaHksIGFlcyhmaWxsPUNvdW50cywgeT0xLCB4PTEpKSArIA0KIyAgICAgZ2d0aXRsZSgiVG9wIDIwIE9yZGVycyBmcm9tIEdyZWVuR2VuZXMgaW4gc2FtcGxlcyBzZXF1ZW5jZWQgYnkgVjYtVjggcmVnaW9uIikrICMgZm9yIHRoZSBtYWluIHRpdGxlDQojICAgICBnZW9tX2Jhcihwb3NpdGlvbj0iZmlsbCIsIHN0YXQ9ImlkZW50aXR5IikgKyBleHBhbmRfbGltaXRzKHkgPSA5LCB4PS05KSAgIyBvciBzb21lIG90aGVyIGFyYml0cmFyaWx5IGxhcmdlIG51bWJlcg0KIyBSRFA0NQ0KIyANCiMgDQojIFJEUDY4IDwtIGdncGxvdCh0b3AyMF9SRFA2OF9QaHksIGFlcyh4ID0gQ291bnRzLCB5ID0gaS5TQU1QTEVfTkFNRSwgZmlsbCA9IFBoeWx1bSkpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIsIHN0YXQgPSAiaWRlbnRpdHkiKQ0KIyAgICAgZ2dwbG90KHRvcDIwX1JEUDY4X1BoeSwgYWVzKGZpbGw9Q291bnRzLCB5PTEsIHg9MSkpICsgDQojICAgICBnZ3RpdGxlKCJUb3AgMjAgT3JkZXJzIGZyb20gR3JlZW5HZW5lcyBpbiBzYW1wbGVzIHNlcXVlbmNlZCBieSBWNi1WOCByZWdpb24iKSsgIyBmb3IgdGhlIG1haW4gdGl0bGUNCiMgICAgIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIGV4cGFuZF9saW1pdHMoeSA9IDksIHg9LTkpICAjIG9yIHNvbWUgb3RoZXIgYXJiaXRyYXJpbHkgbGFyZ2UgbnVtYmVyDQojIFJEUDY4DQoNCg0KDQpjb2xvdXJBc3NpZ25fcGh5ID0gYygiTGVudGlzcGhhZXJhZSI9ImRhcmt2aW9sZXQiLCJOaXRyb3NwaXJhZSI9Im1hcm9vbjMiLCJOYW5vYXJjaGFlYWVvdGEiPSJwYWxldHVycXVvaXNlNCIsIkFybWF0aW1vbmFkZXRlcyI9InNlYWdyZWVuNCIsIkdlbW1hdGltb25hZGV0ZXMiPSJvcmFuZ2VyZWQyIiwgIkNobG9yb2ZsZXhpIj0ib3JhbmdlMyIsIk5pdHJvc3BpbmFlIj0icm95YWxibHVlMyIsIlBhdGVzY2liYWN0ZXJpYSI9InZpb2xldHJlZCIsIk1hcmluaW1pY3JvYmlhIChTQVI0MDYgY2xhZGUpIj0iZGVlcHNreWJsdWUxIiwiRmlybWljdXRlcyI9ImJyb3duMyIsICJFdXJ5YXJjaGFlb3RhIj0iZGFya2N5YW4iLCJBY2lkb2JhY3RlcmlhIj0iZmlyZWJyaWNrMyIsIlZlcnJ1Y29taWNyb2JpYSI9ImdyYXk0NiIsICJUaGF1bWFyY2hhZW90YSI9Im1lZGl1bXNlYWdyZWVuIiwgIiAiPSJtZWRpdW1wdXJwbGUyIiwgIkFjdGlub2JhY3RlcmlhIj0iZ29sZGVucm9kMSIsICJQbGFuY3RvbXljZXRlcyI9Im9yY2hpZDQiLCAiQ3lhbm9iYWN0ZXJpYSI9ImRhcmtzbGF0ZWdyZXkiLCAiQmFjdGVyb2lkZXRlcyI9Im1lZGl1bXB1cnBsZTEiLCJQcm90ZW9iYWN0ZXJpYSI9InNhbG1vbjEiLCAiQ2hsYW15ZGlhZSI9ImxpbmVuIiwgIkRlcGVuZGVudGlhZSI9ImRhcmt0dXJxdW9pc2UiLCAiRXBzaWxvbmJhY3RlcmFlb3RhIj0id2hlYXQyIikNCg0KDQoNCmBgYA0KYGBge3J9DQojQ2hlY2sgdGhlIGFtb3VudCB0aGF0IGNhbm5vdCBiZSBpZGVudGlmaWVkIGluIHRoZSBkaWZmZXJlbnQgZGF0YWJhc2VzDQoNCiNTb3J0IG91dCB0aGUgY291bnRzIG9mIFBoeWxhDQpwaHlsdW1Db3VudDQ1X0dHPC0gYXMuZGF0YS50YWJsZSh0YWJsZShHRzQ1X0Z1bGwkUGh5bHVtKSkgI2NvdW50IGJ5IFBoeWx1bS4NCnBoeWx1bUNvdW50NDVfR0c8LSBwaHlsdW1Db3VudDQ1X0dHW29yZGVyKHBoeWx1bUNvdW50NDVfR0ckTildDQpwaHlsdW1Db3VudDQ1X0dHICNWMSBpcyB0aGUgUGh5bHVtIG5hbWUsIE4gaXMgdGhlIGNvdW50Lg0KDQpzdW1QaHlDb3VudDQ1X0dHIDwtIHN1bShwaHlsdW1Db3VudDQ1X0dHJE4pICNTdW0gYWxsIHRoZSBjb3VudHMNCg0KdW5kZWZQcm9wNDVfR0cgPC0gMTkzNzgvc3VtUGh5Q291bnQ0NV9HRyAjVmFsdWUgbWFudWFsbHkgZm91bmQgYnkgbG9va2luZyBhdCBvdXRwdXQNCnVuZGVmUHJvcDQ1X0dHICNSZXN1bHQ6IDk4LjY3NjA0JSBvZiBwaHlsYSBhcmUgbm90IGRlZmluZWQgd2l0aCBWNC1WNWsgcHJpbWVyLg0KDQoNCiNTb3J0IG91dCB0aGUgY291bnRzIG9mIFBoeWxhDQpwaHlsdW1Db3VudDY4X0dHPC0gYXMuZGF0YS50YWJsZSh0YWJsZShHRzY4X0Z1bGwkUGh5bHVtKSkgI2NvdW50IGJ5IFBoeWx1bS4NCnBoeWx1bUNvdW50NjhfR0c8LSBwaHlsdW1Db3VudDY4X0dHW29yZGVyKHBoeWx1bUNvdW50NjhfR0ckTildDQpwaHlsdW1Db3VudDY4X0dHICNWMSBpcyB0aGUgUGh5bHVtIG5hbWUsIE4gaXMgdGhlIGNvdW50Lg0KDQpzdW1QaHlDb3VudDY4X0dHIDwtIHN1bShwaHlsdW1Db3VudDY4X0dHJE4pICNTdW0gYWxsIHRoZSBjb3VudHMNCg0KdW5kZWZQcm9wNjhfR0cgPC0gOTg0Ni9zdW1QaHlDb3VudDY4X0dHICNWYWx1ZSBtYW51YWxseSBmb3VuZCBieSBsb29raW5nIGF0IG91dHB1dA0KdW5kZWZQcm9wNjhfR0cgI1Jlc3VsdDogOTguODM1NTglIG9mIHBoeWxhIGFyZSBub3QgZGVmaW5lZCB3aXRoIFY2LVY4IHByaW1lci4NCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KYGBge3J9DQojQWJ1bmRhbmNlIG9mIENobG9yb3BsYXN0cyBhbmQgU0FSMTENCg0KI1NJTFZBDQooU0lMVkE0NV9GdWxsKQ0KKFNJTFZBNjhfRnVsbCkNCiNSRFANCihSRFA0NV9GdWxsKQ0KKFJEUDY4X0Z1bGwpDQojR3JlZW5HZW5lcw0KKEdHNDVfRnVsbCkNCihHRzY4X0Z1bGwpDQoNCiMjIyBDaGxvcm9wbGFzdHMgIyMjDQojVjQgVjUNCmNobG9yb19TSUxWQTQ1IDwtIFNJTFZBNDVfRnVsbCAlPiUgZmlsdGVyKE9yZGVyID09ICJDaGxvcm9wbGFzdCIpICNGaWx0ZXIgZm9yIG9ubHkgY2hsb3JvcGxhc3RzDQpjaGxvcm9TdW00NV9TSUxWQSA8LSBzdW0oY2hsb3JvX1NJTFZBNDUkQ291bnRzKQ0KY2hsb3JvU3VtNDVfU0lMVkEgI3RoaXMgaXMgdGhlIG51bWJlciBvZiBzZXF1ZW5jZXMgYXNzb2NpYXRlZCB3aXRoIGNobG9yb3BsYXN0cyBieSBWNFY1DQoNClM0NSA8LSBnZ3Bsb3QoY2hsb3JvX1NJTFZBNDUsIGFlcyh4ID0gQ291bnRzLCB5ID0gaS5TQU1QTEVfTkFNRSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGg9MS41KSkNClM0NQ0KDQoNCmNobG9yb19SRFA0NSA8LSBSRFA0NV9GdWxsICU+JSBmaWx0ZXIoT3JkZXIgPT0gIkNobG9yb3BsYXN0IikgI0ZpbHRlciBmb3Igb25seSBjaGxvcm9wbGFzdHMNCmNobG9yb1N1bTQ1X1JEUCA8LSBzdW0oY2hsb3JvX1JEUDQ1JENvdW50cykNCmNobG9yb1N1bTQ1X1JEUCAjdGhpcyBpcyB0aGUgbnVtYmVyIG9mIHNlcXVlbmNlcyBhc3NvY2lhdGVkIHdpdGggY2hsb3JvcGxhc3RzIGJ5IFY0VjUNCg0KUjQ1IDwtIGdncGxvdChjaGxvcm9fUkRQNDUsIGFlcyh4ID0gQ291bnRzLCB5ID0gaS5TQU1QTEVfTkFNRSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGg9MS41KSkNClI0NQ0KDQoNCiMjIyBDSEFOR0VEIEdHIFRPIENMQVNTDQpjaGxvcm9fR0c0NSA8LSBHRzQ1X0Z1bGwgJT4lIGZpbHRlcihDbGFzcyA9PSAiQ2hsb3JvcGxhc3QiKSAjRmlsdGVyIGZvciBvbmx5IGNobG9yb3BsYXN0cw0KY2hsb3JvU3VtNDVfR0cgPC0gc3VtKGNobG9yb19HRzQ1JENvdW50cykNCmNobG9yb1N1bTQ1X0dHICN0aGlzIGlzIHRoZSBudW1iZXIgb2Ygc2VxdWVuY2VzIGFzc29jaWF0ZWQgd2l0aCBjaGxvcm9wbGFzdHMgYnkgVjRWNQ0KDQpHNDUgPC0gZ2dwbG90KGNobG9yb19HRzQ1LCBhZXMoeCA9IENvdW50cywgeSA9IGkuU0FNUExFX05BTUUpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKQ0KICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoPTEuNSkpDQpHNDUNCg0KDQojVjYgVjgNCmNobG9yb19SRFA2OCA8LSBSRFA2OF9GdWxsICU+JSBmaWx0ZXIoT3JkZXIgPT0gIkNobG9yb3BsYXN0IikgI0ZpbHRlciBmb3Igb25seSBjaGxvcm9wbGFzdHMNCmNobG9yb1N1bTY4X1JEUCA8LSBzdW0oY2hsb3JvX1JEUDY4JENvdW50cykNCmNobG9yb1N1bTY4X1JEUCAjdGhpcyBpcyB0aGUgbnVtYmVyIG9mIHNlcXVlbmNlcyBhc3NvY2lhdGVkIHdpdGggY2hsb3JvcGxhc3RzIGJ5IFY0VjUNCg0KUjY4IDwtIGdncGxvdChjaGxvcm9fUkRQNjgsIGFlcyh4ID0gQ291bnRzLCB5ID0gaS5TQU1QTEVfTkFNRSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGg9MS41KSkNClI2OA0KDQojIyMgQ0hBTkdFRCBHRyBUTyBDTEFTUw0KY2hsb3JvX0dHNjggPC0gR0c2OF9GdWxsICU+JSBmaWx0ZXIoQ2xhc3MgPT0gIkNobG9yb3BsYXN0IikgI0ZpbHRlciBmb3Igb25seSBjaGxvcm9wbGFzdHMNCmNobG9yb1N1bTY4X0dHIDwtIHN1bShjaGxvcm9fR0c2OCRDb3VudHMpDQpjaGxvcm9TdW02OF9HRyAjdGhpcyBpcyB0aGUgbnVtYmVyIG9mIHNlcXVlbmNlcyBhc3NvY2lhdGVkIHdpdGggY2hsb3JvcGxhc3RzIGJ5IFY0VjUNCg0KRzY4IDwtIGdncGxvdChjaGxvcm9fR0c2OCwgYWVzKHggPSBDb3VudHMsIHkgPSBpLlNBTVBMRV9OQU1FKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikNCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aD0xLjUpKQ0KRzY4DQoNCg0KY2hsb3JvX1NJTFZBNjggPC0gU0lMVkE2OF9GdWxsICU+JSBmaWx0ZXIoT3JkZXIgPT0gIkNobG9yb3BsYXN0IikgI0ZpbHRlciBmb3Igb25seSBjaGxvcm9wbGFzdHMNCmNobG9yb1N1bTY4X1NJTFZBIDwtIHN1bShjaGxvcm9fU0lMVkE2OCRDb3VudHMpDQpjaGxvcm9TdW02OF9TSUxWQSAjdGhpcyBpcyB0aGUgbnVtYmVyIG9mIHNlcXVlbmNlcyBhc3NvY2lhdGVkIHdpdGggY2hsb3JvcGxhc3RzIGJ5IFY0VjUNCg0KUzY4IDwtIGdncGxvdChjaGxvcm9fU0lMVkE2OCwgYWVzKHggPSBDb3VudHMsIHkgPSBpLlNBTVBMRV9OQU1FKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikNCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aD0xLjUpKQ0KUzY4DQoNCg0KDQojIyMgU0FSMTEgIyMjDQojVjQgVjUNClNBUl9TSUxWQTQ1IDwtIFNJTFZBNDVfRnVsbCAlPiUgZmlsdGVyKE9yZGVyID09ICJTQVIxMSBjbGFkZSIpICNGaWx0ZXIgZm9yIG9ubHkgU0FScGxhc3RzDQpTQVJTdW00NV9TSUxWQSA8LSBzdW0oU0FSX1NJTFZBNDUkQ291bnRzKQ0KU0FSU3VtNDVfU0lMVkEgI3RoaXMgaXMgdGhlIG51bWJlciBvZiBzZXF1ZW5jZXMgYXNzb2NpYXRlZCB3aXRoIFNBUnBsYXN0cyBieSBWNFY1DQoNClM0NSA8LSBnZ3Bsb3QoU0FSX1NJTFZBNDUsIGFlcyh4ID0gQ291bnRzLCB5ID0gaS5TQU1QTEVfTkFNRSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGg9MS41KSkNClM0NQ0KDQoNClNBUl9SRFA0NSA8LSBSRFA0NV9GdWxsICU+JSBmaWx0ZXIoT3JkZXIgPT0gIlNBUjExIikgI0ZpbHRlciBmb3Igb25seSBTQVJwbGFzdHMNClNBUlN1bTQ1X1JEUCA8LSBzdW0oU0FSX1JEUDQ1JENvdW50cykNClNBUlN1bTQ1X1JEUCAjdGhpcyBpcyB0aGUgbnVtYmVyIG9mIHNlcXVlbmNlcyBhc3NvY2lhdGVkIHdpdGggU0FScGxhc3RzIGJ5IFY0VjUNCg0KUjQ1IDwtIGdncGxvdChTQVJfUkRQNDUsIGFlcyh4ID0gQ291bnRzLCB5ID0gaS5TQU1QTEVfTkFNRSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGg9MS41KSkNClI0NQ0KDQoNClNBUl9HRzQ1IDwtIEdHNDVfRnVsbCAlPiUgZmlsdGVyKE9yZGVyID09ICJTQVIxMSIpICNGaWx0ZXIgZm9yIG9ubHkgU0FScGxhc3RzDQpTQVJTdW00NV9HRyA8LSBzdW0oU0FSX0dHNDUkQ291bnRzKQ0KU0FSU3VtNDVfR0cgI3RoaXMgaXMgdGhlIG51bWJlciBvZiBzZXF1ZW5jZXMgYXNzb2NpYXRlZCB3aXRoIFNBUnBsYXN0cyBieSBWNFY1DQoNCkc0NSA8LSBnZ3Bsb3QoU0FSX0dHNDUsIGFlcyh4ID0gQ291bnRzLCB5ID0gaS5TQU1QTEVfTkFNRSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGg9MS41KSkNCkc0NQ0KDQoNCiNWNiBWOA0KU0FSX1JEUDY4IDwtIFJEUDY4X0Z1bGwgJT4lIGZpbHRlcihPcmRlciA9PSAiU0FSMTEiKSAjRmlsdGVyIGZvciBvbmx5IFNBUnBsYXN0cw0KU0FSU3VtNjhfUkRQIDwtIHN1bShTQVJfUkRQNjgkQ291bnRzKQ0KU0FSU3VtNjhfUkRQICN0aGlzIGlzIHRoZSBudW1iZXIgb2Ygc2VxdWVuY2VzIGFzc29jaWF0ZWQgd2l0aCBTQVJwbGFzdHMgYnkgVjRWNQ0KDQpSNjggPC0gZ2dwbG90KFNBUl9SRFA2OCwgYWVzKHggPSBDb3VudHMsIHkgPSBpLlNBTVBMRV9OQU1FKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikNCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aD0xLjUpKQ0KUjY4DQoNCg0KU0FSX0dHNjggPC0gR0c2OF9GdWxsICU+JSBmaWx0ZXIoT3JkZXIgPT0gIlNBUjExIikgI0ZpbHRlciBmb3Igb25seSBTQVJwbGFzdHMNClNBUlN1bTY4X0dHIDwtIHN1bShTQVJfR0c2OCRDb3VudHMpDQpTQVJTdW02OF9HRyAjdGhpcyBpcyB0aGUgbnVtYmVyIG9mIHNlcXVlbmNlcyBhc3NvY2lhdGVkIHdpdGggU0FScGxhc3RzIGJ5IFY0VjUNCg0KRzY4IDwtIGdncGxvdChTQVJfR0c2OCwgYWVzKHggPSBDb3VudHMsIHkgPSBpLlNBTVBMRV9OQU1FKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikNCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aD0xLjUpKQ0KRzY4DQoNCg0KU0FSX1NJTFZBNjggPC0gU0lMVkE2OF9GdWxsICU+JSBmaWx0ZXIoT3JkZXIgPT0gIlNBUjExIGNsYWRlIikgI0ZpbHRlciBmb3Igb25seSBTQVJwbGFzdHMNClNBUlN1bTY4X1NJTFZBIDwtIHN1bShTQVJfU0lMVkE2OCRDb3VudHMpDQpTQVJTdW02OF9TSUxWQSAjdGhpcyBpcyB0aGUgbnVtYmVyIG9mIHNlcXVlbmNlcyBhc3NvY2lhdGVkIHdpdGggU0FScGxhc3RzIGJ5IFY0VjUNCg0KUzY4IDwtIGdncGxvdChTQVJfU0lMVkE2OCwgYWVzKHggPSBDb3VudHMsIHkgPSBpLlNBTVBMRV9OQU1FKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikNCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aD0xLjUpKQ0KUzY4DQoNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCiNNYXJpYSdzIEFscGhhIERpdmVyc2l0eSBSZWNpcGUNCg0KIycgVmVyc2lvbiAxLjMNCiMnIExhc3QgbW9kaWZpZWQgb24gMjIvMDIvMjAxNg0KIycgU2NyaXB0IFRhc2s6IENhbGN1bGF0ZSBhbHBoYS1kaXZlcnNpdHkNCiMnIEF1dGhvcjogSWxpYXMgTGFna291dmFyZG9zDQojJw0KDQojJyBGb3IgbWVhbmluZ2Z1bCBzcGVjaWVzIHJpY2huZXNzLCB1c2Ugb2Ygbm9ybWFsaXplZCBzZXF1ZW5jZSBjb3VudHMgaXMgZXhwZWN0ZWQuDQojJyBGb3IgcmljaG5lc3MgY2FsY3VsYXRpb24sIG9ubHkgT1RVcyB0aGF0IGFyZSBhYm92ZSAwLjUgbm9ybWFsaXplZCBjb3VudHMgYXJlIGNvbnNpZGVyZWQuDQoNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMjIyMjIyAgICAgICAgICAgICBTZXQgcGFyYW1ldGVycyBpbiB0aGlzIHNlY3Rpb24gbWFudWFsbHkgICAgICAgICAgICAgICAgICAjIyMjIyMNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCg0KIycgUGxlYXNlIHNldCB0aGUgZGlyZWN0b3J5IG9mIHRoZSBzY3JpcHQgYXMgd29ya2luZyBmb2xkZXIgKGUuZyBEOi9NeVN0dWR5L05HUy9SaGVhL2FscGhhLWRpdmVyc2l0eSkNCiMnIE5vdGU6IHRoZSBwYXRoIGlzIGRlbm90ZWQgYnkgZm9yd2FyZCBzbGFzaCAiLyINCg0KDQojIyMjIyMgICAgICAgICAgICAgICAgICBOTyBDSEFOR0VTIEFSRSBORUVERUQgQkVMT1cgVEhJUyBMSU5FICAgICAgICAgICAgICAgIyMjIyMjDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyMjIyMjICAgICAgICAgICAgICAgICAgICAgICAgRGl2ZXJzaXR5IEZ1bmN0aW9ucyAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIyMjIyANCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCg0KIyBDYWxjdWxhdGUgdGhlIHNwZWNpZXMgcmljaG5lc3MgaW4gYSBzYW1wbGUNCg0KU3BlY2llcy5yaWNobmVzcyA8LSBmdW5jdGlvbih4KQ0KDQp7DQoNCiAgIyBDb3VudCBvbmx5IHRoZSBPVFVzIHRoYXQgYXJlIHByZXNlbnQgPjAuNSBub3JtYWxpemVkIGNvdW50cyAobm9ybWFsaXphdGlvbiBwcm9kdWNlcyByZWFsIHZhbHVlcyBmb3IgY291bnRzKQ0KDQogIGNvdW50PXN1bSh4W3g+MC41XV4wKQ0KDQogIHJldHVybihjb3VudCkNCg0KfQ0KDQoNCiMgQ2FsY3VsYXRlIHRoZSBTaGFubm9uIGRpdmVyc2l0eSBpbmRleA0KDQpTaGFubm9uLmVudHJvcHkgPC0gZnVuY3Rpb24oeCkNCg0Kew0KDQogIHRvdGFsPXN1bSh4KQ0KDQogIHNlPS1zdW0oeFt4PjBdL3RvdGFsKmxvZyh4W3g+MF0vdG90YWwpKQ0KDQogIHJldHVybihzZSkNCg0KfQ0KDQoNCg0KIyBDYWxjdWxhdGUgdGhlIGVmZmVjdGl2ZSBudW1iZXIgb2Ygc3BlY2llcyBmb3IgU2hhbm5vbg0KDQpTaGFubm9uLmVmZmVjdGl2ZSA8LSBmdW5jdGlvbih4KQ0KDQp7DQoNCiAgdG90YWw9c3VtKHgpDQoNCiAgc2U9cm91bmQoZXhwKC1zdW0oeFt4PjBdL3RvdGFsKmxvZyh4W3g+MF0vdG90YWwpKSksZGlnaXRzID0yKQ0KDQogIHJldHVybihzZSkNCg0KfQ0KDQoNCg0KIyBDYWxjdWxhdGUgdGhlIFNpbXBzb24gZGl2ZXJzaXR5IGluZGV4DQoNClNpbXBzb24uY29uY2VudHJhdGlvbiA8LSBmdW5jdGlvbih4KQ0KDQp7DQoNCiAgdG90YWw9c3VtKHgpDQoNCiAgc2k9c3VtKCh4W3g+MF0vdG90YWwpXjIpDQoNCiAgcmV0dXJuKHNpKQ0KDQp9DQoNCg0KDQojIENhbGN1bGF0ZSB0aGUgZWZmZWN0aXZlIG51bWJlciBvZiBzcGVjaWVzIGZvciBTaW1wc29uDQoNClNpbXBzb24uZWZmZWN0aXZlIDwtIGZ1bmN0aW9uKHgpDQoNCnsNCg0KICB0b3RhbD1zdW0oeCkNCg0KICBzaT1yb3VuZCgxL3N1bSgoeFt4PjBdL3RvdGFsKV4yKSxkaWdpdHMgPTIpDQoNCiAgcmV0dXJuKHNpKQ0KDQp9DQoNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMjIyMjIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWFpbiBTY3JpcHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIyMjIyMgDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQoNCiMgUmVhZCBhIG5vcm1hbGl6ZWQgT1RVLXRhYmxlIHdpdGhvdXQgdGF4b25vbXkgIA0KDQojIG90dV90YWJsZSA8LSByZWFkLnRhYmxlIChmaWxlX25hbWUsIA0KIyANCiMgICAgICAgICAgICAgICAgICAgICAgICBjaGVjay5uYW1lcyA9IEZBTFNFLCANCiMgDQojICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyPVRSVUUsIA0KIyANCiMgICAgICAgICAgICAgICAgICAgICAgICBkZWM9Ii4iLCANCiMgDQojICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIlx0IiwNCiMgDQojICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gMSkNCg0KDQpvdHU0NTwtIHJlYWQuY3N2KCJHOi9EZXNrdG9wL0ZvbGRlcnMvRWR1LzJdIEVBUy9UaGVzaXMvUmVhbF9Db250ZW50L0RhdGFfRmlsZXMvVjRWNS9WNFY1X19BU1ZfdGFibGUuY3N2Iiwgcm93Lm5hbWVzPTEpICMscm93Lm5hbWVzPTEgIGhlYWRlciA9IFQNCm90dTY4PC0gcmVhZC5jc3YoIkc6L0Rlc2t0b3AvRm9sZGVycy9FZHUvMl0gRUFTL1RoZXNpcy9SZWFsX0NvbnRlbnQvRGF0YV9GaWxlcy9WNlY4L1Y2VjhfX0FTVl90YWJsZS5jc3YiLCByb3cubmFtZXM9MSkNCmhlYWQob3R1NDUpIA0KaGVhZChvdHU2OCkNCg0Kb3R1X3RhYmxlNDUgPC0gb3R1NDUNCm90dV90YWJsZTY4IDwtIG90dTY4DQoNCiMgQ2xlYW4gdGFibGUgZnJvbSBlbXB0eSBsaW5lcw0KI290dV90YWJsZSA8LSBvdHVfdGFibGVbIWFwcGx5KGlzLm5hKG90dV90YWJsZSkgfCBvdHVfdGFibGU9PSIiLDEsYWxsKSxdDQoNCiMgT3JkZXIgYW5kIHRyYW5zcG9zZSBPVFUtdGFibGUNCg0KbXlfb3R1X3RhYmxlNDUgPC0gb3R1X3RhYmxlNDVbLG9yZGVyKG5hbWVzKG90dV90YWJsZTQ1KSldIA0KbXlfb3R1X3RhYmxlNDUgPC1kYXRhLmZyYW1lKHQobXlfb3R1X3RhYmxlNDUpKQ0KDQpteV9vdHVfdGFibGU2OCA8LSBvdHVfdGFibGU2OFssb3JkZXIobmFtZXMob3R1X3RhYmxlNjgpKV0gDQpteV9vdHVfdGFibGU2OCA8LWRhdGEuZnJhbWUodChteV9vdHVfdGFibGU2OCkpDQoNCg0KIyBBcHBseSBkaXZlcnNpdHkgZnVuY3Rpb25zIHRvIHRhYmxlDQpvdHVzX2Rpdl9zdGF0czQ1PC1kYXRhLmZyYW1lKG15X290dV90YWJsZTQ1WywwXSkNCm90dXNfZGl2X3N0YXRzNjg8LWRhdGEuZnJhbWUobXlfb3R1X3RhYmxlNjhbLDBdKQ0KDQpzYW1wbGVOYW1lczwtYygiVklPXzMzXzE1bSIsIlZJT18yXzVtIiwiVklPXzMzXzUwbSIsIlZJT18zM18yMDBtIiwiVklPXzJfMTBtIiwiVklPXzMyXzEyNW0iLCJWSU9fMzBfNDdtIiwiVklPXzMxXzQwbSIsIlZJT18yNF8xN20iLCJWSU9fMjhfNG0iLCJWSU9fMzJfMzUwbSIsIlZJT18zMV82N20iLCJWSU9fMjhfMTJtIiwiVklPXzIyXzdtIiwiVklPXzEzXzVtIiwiVklPXzEzXzIwbSIsIlZJT18yMl8yMG0iLCJWSU9fMjJfMTE1bSIsIlZJT18xM18xNDBtIiwiVklPXzZfNW0iLCJWSU9fN181bSIsIlZJT185X3N1cmZhY2UiLCJWSU9fN18yN20iLCJWSU9fMTBfOTVtIiwiVGVyXzEyMiIsIlZJT18zOV83bSIsIlZJT180NF8xNDVtIikNCg0Kb3R1c19kaXZfc3RhdHM0NSRzYW1wbGVOYW1lcyA8LSBzYW1wbGVOYW1lcw0Kb3R1c19kaXZfc3RhdHM0NSRSaWNobmVzczwtYXBwbHkobXlfb3R1X3RhYmxlNDUsMSxTcGVjaWVzLnJpY2huZXNzKQ0Kb3R1c19kaXZfc3RhdHM0NSRTaGFubm9uPC1hcHBseShteV9vdHVfdGFibGU0NSwxLFNoYW5ub24uZW50cm9weSkNCm90dXNfZGl2X3N0YXRzNDUkU2hhbm5vbi5lZmZlY3RpdmU8LWFwcGx5KG15X290dV90YWJsZTQ1LDEsU2hhbm5vbi5lZmZlY3RpdmUpDQpvdHVzX2Rpdl9zdGF0czQ1JFNpbXBzb248LWFwcGx5KG15X290dV90YWJsZTQ1LDEsU2ltcHNvbi5jb25jZW50cmF0aW9uKQ0Kb3R1c19kaXZfc3RhdHM0NSRTaW1wc29uLmVmZmVjdGl2ZTwtYXBwbHkobXlfb3R1X3RhYmxlNDUsMSxTaW1wc29uLmVmZmVjdGl2ZSkNCg0Kb3R1c19kaXZfc3RhdHM2OCRzYW1wbGVOYW1lcyA8LSBzYW1wbGVOYW1lcw0Kb3R1c19kaXZfc3RhdHM2OCRSaWNobmVzczwtYXBwbHkobXlfb3R1X3RhYmxlNjgsMSxTcGVjaWVzLnJpY2huZXNzKQ0Kb3R1c19kaXZfc3RhdHM2OCRTaGFubm9uPC1hcHBseShteV9vdHVfdGFibGU2OCwxLFNoYW5ub24uZW50cm9weSkNCm90dXNfZGl2X3N0YXRzNjgkU2hhbm5vbi5lZmZlY3RpdmU8LWFwcGx5KG15X290dV90YWJsZTY4LDEsU2hhbm5vbi5lZmZlY3RpdmUpDQpvdHVzX2Rpdl9zdGF0czY4JFNpbXBzb248LWFwcGx5KG15X290dV90YWJsZTY4LDEsU2ltcHNvbi5jb25jZW50cmF0aW9uKQ0Kb3R1c19kaXZfc3RhdHM2OCRTaW1wc29uLmVmZmVjdGl2ZTwtYXBwbHkobXlfb3R1X3RhYmxlNjgsMSxTaW1wc29uLmVmZmVjdGl2ZSkNCg0KDQoNCg0KIyBXcml0ZSB0aGUgcmVzdWx0cyBpbiBhIGZpbGUgYW5kIGNvcHkgaW4gZGlyZWN0b3J5ICJTZXJpYWwtR3JvdXAtQ29tcGFyaXNvbnMiIGlmIGV4aXN0aW5nDQoNCiNTYXZlIG91dHB1dA0KI3dyaXRlLnRhYmxlKG90dXNfZGl2X3N0YXRzLCAiRzovRGVza3RvcC9Gb2xkZXJzL0VkdS8yXSBFQVMvVGhlc2lzL1JlYWxfQ29udGVudC9EYXRhX0ZpbGVzL1Y0VjUvYWxwaGEtZGl2ZXJzaXR5LnRhYiIsIHNlcD0iXHQiLCBjb2wubmFtZXM9TkEsIHF1b3RlPUZBTFNFKQ0KI3dyaXRlLnRhYmxlKG90dXNfZGl2X3N0YXRzLCAiRzovRGVza3RvcC9Gb2xkZXJzL0VkdS8yXSBFQVMvVGhlc2lzL1JlYWxfQ29udGVudC9EYXRhX0ZpbGVzL1Y2VjgvYWxwaGEtZGl2ZXJzaXR5LnRhYiIsIHNlcD0iXHQiLCBjb2wubmFtZXM9TkEsIHF1b3RlPUZBTFNFKQ0KDQojc3VwcHJlc3NXYXJuaW5ncyAodHJ5KHdyaXRlLnRhYmxlKG90dXNfZGl2X3N0YXRzW2MoMSwzLDUpXSwgIi4uLzUuU2VyaWFsLUdyb3VwLUNvbXBhcmlzb25zL2FscGhhLWRpdmVyc2l0eS50YWIiLCBzZXAgPSAiXHQiLGNvbC5uYW1lcyA9IE5BLCBxdW90ZSA9IEZBTFNFKSwgc2lsZW50ID1UUlVFKSkNCg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyMjIyMjICAgICAgICAgICAgICAgICAgICAgICAgICBFbmQgb2YgU2NyaXB0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIyMjIyANCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQojc3VtbWFyeSBzdGF0cw0KbWVhbihvdHVzX2Rpdl9zdGF0czQ1JFJpY2huZXNzKQ0KbWVhbihvdHVzX2Rpdl9zdGF0czQ1JFNoYW5ub24pDQptZWFuKG90dXNfZGl2X3N0YXRzNDUkU2hhbm5vbi5lZmZlY3RpdmUpDQptZWFuKG90dXNfZGl2X3N0YXRzNDUkU2ltcHNvbikNCm1lYW4ob3R1c19kaXZfc3RhdHM0NSRTaW1wc29uLmVmZmVjdGl2ZSkNCm1lZGlhbihvdHVzX2Rpdl9zdGF0czQ1JFJpY2huZXNzKQ0KbWVkaWFuKG90dXNfZGl2X3N0YXRzNDUkU2hhbm5vbikNCm1lZGlhbihvdHVzX2Rpdl9zdGF0czQ1JFNoYW5ub24uZWZmZWN0aXZlKQ0KbWVkaWFuKG90dXNfZGl2X3N0YXRzNDUkU2ltcHNvbikNCm1lZGlhbihvdHVzX2Rpdl9zdGF0czQ1JFNpbXBzb24uZWZmZWN0aXZlKQ0KDQptZWFuKG90dXNfZGl2X3N0YXRzNjgkUmljaG5lc3MpDQptZWFuKG90dXNfZGl2X3N0YXRzNjgkU2hhbm5vbikNCm1lYW4ob3R1c19kaXZfc3RhdHM2OCRTaGFubm9uLmVmZmVjdGl2ZSkNCm1lYW4ob3R1c19kaXZfc3RhdHM2OCRTaW1wc29uKQ0KbWVhbihvdHVzX2Rpdl9zdGF0czY4JFNpbXBzb24uZWZmZWN0aXZlKQ0KbWVkaWFuKG90dXNfZGl2X3N0YXRzNjgkUmljaG5lc3MpDQptZWRpYW4ob3R1c19kaXZfc3RhdHM2OCRTaGFubm9uKQ0KbWVkaWFuKG90dXNfZGl2X3N0YXRzNjgkU2hhbm5vbi5lZmZlY3RpdmUpDQptZWRpYW4ob3R1c19kaXZfc3RhdHM2OCRTaW1wc29uKQ0KbWVkaWFuKG90dXNfZGl2X3N0YXRzNjgkU2ltcHNvbi5lZmZlY3RpdmUpDQoNCg0KI0JveHBsb3QNCiNodHRwOi8vd3d3LnN0aGRhLmNvbS9lbmdsaXNoL3dpa2kvZ2dwbG90Mi1ib3gtcGxvdC1xdWljay1zdGFydC1ndWlkZS1yLXNvZnR3YXJlLWFuZC1kYXRhLXZpc3VhbGl6YXRpb24NCg0KI0NvbWJpbmVkIHRhYmxlDQpwcmltZXI9cmVwKGMoInY0NSIsInY2OCIpLGVhY2g9MjcpDQoNCm90dV9zdGF0cyA8LSBkYXRhLnRhYmxlKCkNCm90dV9zdGF0cyA8LSByYmluZChvdHVzX2Rpdl9zdGF0czQ1LCBvdHVzX2Rpdl9zdGF0czY4KQ0Kb3R1X3N0YXRzJHByaW1lciA8LSBwcmltZXINCm90dV9zdGF0cw0KDQojUmljaG5lc3MNCnAgPC0gZ2dwbG90KG90dV9zdGF0cywgYWVzKHg9cHJpbWVyLCB5PVJpY2huZXNzLCBmaWxsPXByaW1lcikpICsgDQogIGdndGl0bGUoIkNvbXBhcmlzb24gb2YgcmVsYXRpdmUgYWJ1bmRhbmNlIGRldGVjdGVkIGJldHdlZW4gVjQtVjUgYW5kIFY2LVY4IHByaW1lcnMiKSsNCiAgdGhlbWUoYXhpcy50ZXh0Lng9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemU9MTIpKSArZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJPcmRlciIpKSt5bGFiKGxhYmVsPSJSZWxhdGl2ZSBhYnVuZGFuY2UiKSsNCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyPSJibGFjayIsIG91dGxpZXIuc2hhcGU9MTYsb3V0bGllci5zaXplPTIsIG5vdGNoPUZBTFNFKSsNCiAgc3RhdF9zdW1tYXJ5KGZ1bj1tZWFuLCBnZW9tPSJwb2ludCIsIHNoYXBlPTIzLCBzaXplPTMpDQoNCnANCg0KI1NoYW5ub24NCnAgPC0gZ2dwbG90KG90dV9zdGF0cywgYWVzKHg9cHJpbWVyLCB5PVNoYW5ub24sIGZpbGw9cHJpbWVyKSkgKyANCiAgZ2d0aXRsZSgiQ29tcGFyaXNvbiBvZiBTaGFubm9uIGRpdmVyc2l0eSBkZXRlY3RlZCBiZXR3ZWVuIFY0LVY1IGFuZCBWNi1WOCBwcmltZXJzIikrDQogIHRoZW1lKGF4aXMudGV4dC54PSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplPTEyKSkgK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT0iT3JkZXIiKSkreWxhYihsYWJlbD0iUmVsYXRpdmUgYWJ1bmRhbmNlIikrDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91cj0iYmxhY2siLCBvdXRsaWVyLnNoYXBlPTE2LG91dGxpZXIuc2l6ZT0yLCBub3RjaD1GQUxTRSkrDQogIHN0YXRfc3VtbWFyeShmdW49bWVhbiwgZ2VvbT0icG9pbnQiLCBzaGFwZT0yMywgc2l6ZT0zKQ0KDQpwDQoNCg0KDQpgYGANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K